<commit_before>package response

import (
	"bytes"
	"errors"
	"net/http"
	"net/http/httptest"
	"testing"
)

type jsonResponse struct {
	Name string `json:"name"`
}

func TestAsJSON(t *testing.T) {
	h := AsJSON(http.HandlerFunc(func(_ http.ResponseWriter, r *http.Request) {
		WithPayload(r.Context(), jsonResponse{"John"})
	}))

	w := httptest.NewRecorder()
	req, err := http.NewRequest("GET", "/x", nil)
	if err != nil {
		t.Fatal(err)
	}

	h.ServeHTTP(w, req)

	header := w.Header()
	if header.Get("Content-Type") != "application/json" {
		t.Error("AsJSON did not set proper headers")
	}

	cmp := bytes.Compare(w.Body.Bytes(), append([]byte(`{"name":"John"}`), 10))
	if cmp != 0 {
		t.Errorf("AsJSON returned wrong body: %s | %d", w.Body.String(), cmp)
	}
}

func TestErrorAsJSON(t *testing.T) {
	h := AsJSON(http.HandlerFunc(func(_ http.ResponseWriter, r *http.Request) {
		WithError(r.Context(), HTTPError{
			Code:    http.StatusBadRequest,
			Error:   errors.New("response error"),
			Message: "Invalid request",
		})
	}))

	w := httptest.NewRecorder()
	req, err := http.NewRequest("GET", "/x", nil)
	if err != nil {
		t.Fatal(err)
	}

	h.ServeHTTP(w, req)

	header := w.Header()
	if header.Get("Content-Type") != "application/json" {
		t.Error("AsJSON did not set proper headers")
	}

	if w.Code != http.StatusBadRequest {
		t.Errorf("AsJSON error code not handled %d", w.Code)
	}
}

func TestErrorPointerAsJSON(t *testing.T) {
	h := AsJSON(http.HandlerFunc(func(_ http.ResponseWriter, r *http.Request) {
		WithPayload(r.Context(), &HTTPError{
			Code:    http.StatusBadRequest,
			Error:   errors.New("response error"),
			Message: "Invalid request",
		})
	}))

	w := httptest.NewRecorder()
	req, err := http.NewRequest("GET", "/x", nil)
	if err != nil {
		t.Fatal(err)
	}

	h.ServeHTTP(w, req)

	header := w.Header()
	if header.Get("Content-Type") != "application/json" {
		t.Error("AsJSON did not set proper headers")
	}

	if w.Code != http.StatusBadRequest {
		t.Errorf("AsJSON error code not handled %d", w.Code)
	}
}

// func TestInvalidPayloadAsJSON(t *testing.T) {
// 	h := AsJSON(http.HandlerFunc(func(_ http.ResponseWriter, r *http.Request) {
// 		WithPayload(r.Context(), nil)
// 	}))

// 	w := httptest.NewRecorder()
// 	req, err := http.NewRequest("GET", "/x", nil)
// 	if err != nil {
// 		t.Fatal(err)
// 	}

// 	h.ServeHTTP(w, req)

// 	header := w.Header()
// 	if header.Get("Content-Type") != "application/json" {
// 		t.Error("AsJSON did not set proper headers")
// 	}

// 	if w.Code != http.StatusInternalServerError {
// 		t.Errorf("AsJSON error code not handled %d", w.Code)
// 	}
// }
<commit_msg>Test invalid json<commit_after>package response

import (
	"bytes"
	"errors"
	"net/http"
	"net/http/httptest"
	"testing"
)

type jsonResponse struct {
	Name string `json:"name"`
}

func TestAsJSON(t *testing.T) {
	h := AsJSON(http.HandlerFunc(func(_ http.ResponseWriter, r *http.Request) {
		WithPayload(r.Context(), jsonResponse{"John"})
	}))

	w := httptest.NewRecorder()
	req, err := http.NewRequest("GET", "/x", nil)
	if err != nil {
		t.Fatal(err)
	}

	h.ServeHTTP(w, req)

	header := w.Header()
	if header.Get("Content-Type") != "application/json" {
		t.Error("AsJSON did not set proper headers")
	}

	cmp := bytes.Compare(w.Body.Bytes(), append([]byte(`{"name":"John"}`), 10))
	if cmp != 0 {
		t.Errorf("AsJSON returned wrong body: %s | %d", w.Body.String(), cmp)
	}
}

func TestErrorAsJSON(t *testing.T) {
	h := AsJSON(http.HandlerFunc(func(_ http.ResponseWriter, r *http.Request) {
		WithError(r.Context(), HTTPError{
			Code:    http.StatusBadRequest,
			Error:   errors.New("response error"),
			Message: "Invalid request",
		})
	}))

	w := httptest.NewRecorder()
	req, err := http.NewRequest("GET", "/x", nil)
	if err != nil {
		t.Fatal(err)
	}

	h.ServeHTTP(w, req)

	header := w.Header()
	if header.Get("Content-Type") != "application/json" {
		t.Error("AsJSON did not set proper headers")
	}

	if w.Code != http.StatusBadRequest {
		t.Errorf("AsJSON error code not handled %d", w.Code)
	}
}

func TestErrorPointerAsJSON(t *testing.T) {
	h := AsJSON(http.HandlerFunc(func(_ http.ResponseWriter, r *http.Request) {
		WithPayload(r.Context(), &HTTPError{
			Code:    http.StatusBadRequest,
			Error:   errors.New("response error"),
			Message: "Invalid request",
		})
	}))

	w := httptest.NewRecorder()
	req, err := http.NewRequest("GET", "/x", nil)
	if err != nil {
		t.Fatal(err)
	}

	h.ServeHTTP(w, req)

	header := w.Header()
	if header.Get("Content-Type") != "application/json" {
		t.Error("AsJSON did not set proper headers")
	}

	if w.Code != http.StatusBadRequest {
		t.Errorf("AsJSON error code not handled %d", w.Code)
	}
}

func TestInvalidPayloadAsJSON(t *testing.T) {
	h := AsJSON(http.HandlerFunc(func(_ http.ResponseWriter, r *http.Request) {
		WithPayload(r.Context(), make(chan int))
	}))

	w := httptest.NewRecorder()
	req, err := http.NewRequest("GET", "/x", nil)
	if err != nil {
		t.Fatal(err)
	}

	h.ServeHTTP(w, req)

	header := w.Header()
	if header.Get("Content-Type") != "application/json" {
		t.Error("AsJSON did not set proper headers")
	}

	if w.Code != http.StatusInternalServerError {
		t.Errorf("AsJSON error code not handled %d", w.Code)
	}
}
<|endoftext|>


<commit_before>/*
Copyright 2019 The Skaffold 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 config

import (
	"strings"

	"github.com/GoogleContainerTools/skaffold/pkg/skaffold/schema/latest"
)

// PortForwardOptions are options set by the command line for port forwarding
// with additional configuration information as well
type PortForwardOptions struct {
	Enabled     bool
	ForwardPods bool
}

// SkaffoldOptions are options that are set by command line arguments not included
// in the config file itself
type SkaffoldOptions struct {
	ConfigurationFile     string
	GlobalConfig          string
	Cleanup               bool
	Notification          bool
	Tail                  bool
	TailDev               bool
	SkipTests             bool
	CacheArtifacts        bool
	EnableRPC             bool
	Force                 bool
	NoPrune               bool
	NoPruneChildren       bool
	StatusCheck           bool
	AutoBuild             bool
	AutoSync              bool
	AutoDeploy            bool
	RenderOnly            bool
	ProfileAutoActivation bool
	DryRun                bool
	PortForward           PortForwardOptions
	CustomTag             string
	Namespace             string
	CacheFile             string
	Trigger               string
	KubeContext           string
	KubeConfig            string
	WatchPollInterval     int
	DefaultRepo           StringOrUndefined
	CustomLabels          []string
	TargetImages          []string
	Profiles              []string
	InsecureRegistries    []string
	Command               string
	RPCPort               int
	RPCHTTPPort           int
	SkipBuild             bool
	// TODO(https://github.com/GoogleContainerTools/skaffold/issues/3668):
	// remove minikubeProfile from here and instead detect it by matching the
	// kubecontext API Server to minikube profiles
	MinikubeProfile string
}

// Prune returns true iff the user did NOT specify the --no-prune flag,
// and the user did NOT specify the --cache-artifacts flag.
func (opts *SkaffoldOptions) Prune() bool {
	return !opts.NoPrune && !opts.CacheArtifacts
}

func (opts *SkaffoldOptions) IsDevMode() bool {
	return opts.Command == "dev"
}

func (opts *SkaffoldOptions) IsDebugMode() bool {
	return opts.Command == "debug"
}

func (opts *SkaffoldOptions) IsTargetImage(artifact *latest.Artifact) bool {
	if len(opts.TargetImages) == 0 {
		return true
	}

	for _, targetImage := range opts.TargetImages {
		if strings.Contains(artifact.ImageName, targetImage) {
			return true
		}
	}

	return false
}
<commit_msg>Fix maligned linter errors<commit_after>/*
Copyright 2019 The Skaffold 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 config

import (
	"strings"

	"github.com/GoogleContainerTools/skaffold/pkg/skaffold/schema/latest"
)

// PortForwardOptions are options set by the command line for port forwarding
// with additional configuration information as well
type PortForwardOptions struct {
	Enabled     bool
	ForwardPods bool
}

// SkaffoldOptions are options that are set by command line arguments not included
// in the config file itself
type SkaffoldOptions struct {
	ConfigurationFile     string
	GlobalConfig          string
	Cleanup               bool
	Notification          bool
	Tail                  bool
	TailDev               bool
	SkipTests             bool
	CacheArtifacts        bool
	EnableRPC             bool
	Force                 bool
	NoPrune               bool
	NoPruneChildren       bool
	StatusCheck           bool
	AutoBuild             bool
	AutoSync              bool
	AutoDeploy            bool
	RenderOnly            bool
	ProfileAutoActivation bool
	DryRun                bool
	SkipBuild             bool
	PortForward           PortForwardOptions
	CustomTag             string
	Namespace             string
	CacheFile             string
	Trigger               string
	KubeContext           string
	KubeConfig            string
	WatchPollInterval     int
	DefaultRepo           StringOrUndefined
	CustomLabels          []string
	TargetImages          []string
	Profiles              []string
	InsecureRegistries    []string
	Command               string
	RPCPort               int
	RPCHTTPPort           int
	// TODO(https://github.com/GoogleContainerTools/skaffold/issues/3668):
	// remove minikubeProfile from here and instead detect it by matching the
	// kubecontext API Server to minikube profiles
	MinikubeProfile string
}

// Prune returns true iff the user did NOT specify the --no-prune flag,
// and the user did NOT specify the --cache-artifacts flag.
func (opts *SkaffoldOptions) Prune() bool {
	return !opts.NoPrune && !opts.CacheArtifacts
}

func (opts *SkaffoldOptions) IsDevMode() bool {
	return opts.Command == "dev"
}

func (opts *SkaffoldOptions) IsDebugMode() bool {
	return opts.Command == "debug"
}

func (opts *SkaffoldOptions) IsTargetImage(artifact *latest.Artifact) bool {
	if len(opts.TargetImages) == 0 {
		return true
	}

	for _, targetImage := range opts.TargetImages {
		if strings.Contains(artifact.ImageName, targetImage) {
			return true
		}
	}

	return false
}
<|endoftext|>


<commit_before>package rtinstances

import (
	"github.com/jfrogdev/jfrog-cli-go/missioncontrol/utils"
	"github.com/jfrogdev/jfrog-cli-go/utils/cliutils"
	"github.com/jfrogdev/jfrog-cli-go/utils/ioutils"
	"github.com/jfrogdev/jfrog-cli-go/utils/config"
	"encoding/json"
	"io/ioutil"
	"fmt"
	"os"
)

func AttachLic(instanceName string, flags *AttachLicFlags) {
	prepareLicenseFile(flags.LicensePath, flags.Override)
	postContent := utils.LicenseRequestContent{
		Name: 	  	 instanceName,
		BucketKey:	 flags.BucketKey,
		NodeID:	     flags.NodeId,
		Deploy:	     flags.Deploy}
	fmt.Println(postContent)
	requestContent, err := json.Marshal(postContent)
	if err != nil {
		cliutils.Exit(cliutils.ExitCodeError, "Failed to marshal json. " + cliutils.GetDocumentationMessage())
	}
	missionControlUrl := flags.MissionControlDetails.Url + "api/v1/buckets/" + flags.BucketId + "/licenses";
	httpClientDetails := utils.GetMissionControlHttpClientDetails(flags.MissionControlDetails)
	resp, body := ioutils.SendPost(missionControlUrl, requestContent, httpClientDetails)
	if resp.StatusCode != 200 {
		if flags.LicensePath != "" {
			os.Remove(flags.LicensePath)
		}
		cliutils.Exit(cliutils.ExitCodeError, resp.Status + ". " + utils.ReadMissionControlHttpMessage(body))
	}
	fmt.Println("Mission Control response: " + resp.Status)
	if flags.LicensePath == "" {
		requestContent, err := json.Marshal(extractJsonValue(body))
		cliutils.CheckError(err)
		fmt.Println(string(requestContent))
	} else {
		licenseKey := getLicenseFromJson(body)
		saveLicense(flags.LicensePath, licenseKey)
	}
}

func getLicenseFromJson(body []byte) (licenseKey [] byte) {
	licenseKey = []byte(extractJsonValue(body).LicenseKey)
	return
}

func extractJsonValue(body []byte) Message {
	data := &Data{}
	err := json.Unmarshal(body, &data);
	cliutils.CheckError(err)
	return data.Data
}

func prepareLicenseFile(filepath string, overrideFile bool) {
	if filepath == "" {
		return
	}
	if ioutils.IsDir(filepath) {
		cliutils.Exit(cliutils.ExitCodeError, filepath + " is a directory.")
	}
	if !overrideFile && ioutils.IsFileExists(filepath) {
		cliutils.Exit(cliutils.ExitCodeError, "File already exist, in case you wish to override the file use --override flag")
	}
	_, dir := ioutils.GetFileAndDirFromPath(filepath)
	isPathExists := ioutils.IsPathExists(dir)
	if !isPathExists {
		os.MkdirAll(dir, 0700)
	}
	err := ioutil.WriteFile(filepath, nil, 0777)
	cliutils.CheckError(err)
}

func saveLicense(filepath string, content []byte){
	if filepath == "" {
		return
	}
	err := ioutil.WriteFile(filepath, content, 0777)
	cliutils.CheckError(err)
}

type AttachLicFlags struct {
	MissionControlDetails *config.MissionControlDetails
	LicensePath 	      string
	NodeId 			      string
	BucketKey 			  string
	BucketId 			  string
	Override 			  bool
	Deploy 			  	  bool
}

type Message struct {
	LicenseKey string `json:"licenseKey,omitempty"`
}

type Data struct {
	Data Message
}
<commit_msg>add mc cli attach-lic deploy flag<commit_after>package rtinstances

import (
	"github.com/jfrogdev/jfrog-cli-go/missioncontrol/utils"
	"github.com/jfrogdev/jfrog-cli-go/utils/cliutils"
	"github.com/jfrogdev/jfrog-cli-go/utils/ioutils"
	"github.com/jfrogdev/jfrog-cli-go/utils/config"
	"encoding/json"
	"io/ioutil"
	"fmt"
	"os"
)

func AttachLic(instanceName string, flags *AttachLicFlags) {
	prepareLicenseFile(flags.LicensePath, flags.Override)
	postContent := utils.LicenseRequestContent{
		Name: 	  	 instanceName,
		BucketKey:	 flags.BucketKey,
		NodeID:	     flags.NodeId,
		Deploy:	     flags.Deploy}
	requestContent, err := json.Marshal(postContent)
	if err != nil {
		cliutils.Exit(cliutils.ExitCodeError, "Failed to marshal json. " + cliutils.GetDocumentationMessage())
	}
	missionControlUrl := flags.MissionControlDetails.Url + "api/v1/buckets/" + flags.BucketId + "/licenses";
	httpClientDetails := utils.GetMissionControlHttpClientDetails(flags.MissionControlDetails)
	resp, body := ioutils.SendPost(missionControlUrl, requestContent, httpClientDetails)
	if resp.StatusCode != 200 {
		if flags.LicensePath != "" {
			os.Remove(flags.LicensePath)
		}
		cliutils.Exit(cliutils.ExitCodeError, resp.Status + ". " + utils.ReadMissionControlHttpMessage(body))
	}
	fmt.Println("Mission Control response: " + resp.Status)
	if flags.LicensePath == "" {
		requestContent, err := json.Marshal(extractJsonValue(body))
		cliutils.CheckError(err)
		fmt.Println(string(requestContent))
	} else {
		licenseKey := getLicenseFromJson(body)
		saveLicense(flags.LicensePath, licenseKey)
	}
}

func getLicenseFromJson(body []byte) (licenseKey [] byte) {
	licenseKey = []byte(extractJsonValue(body).LicenseKey)
	return
}

func extractJsonValue(body []byte) Message {
	data := &Data{}
	err := json.Unmarshal(body, &data);
	cliutils.CheckError(err)
	return data.Data
}

func prepareLicenseFile(filepath string, overrideFile bool) {
	if filepath == "" {
		return
	}
	if ioutils.IsDir(filepath) {
		cliutils.Exit(cliutils.ExitCodeError, filepath + " is a directory.")
	}
	if !overrideFile && ioutils.IsFileExists(filepath) {
		cliutils.Exit(cliutils.ExitCodeError, "File already exist, in case you wish to override the file use --override flag")
	}
	_, dir := ioutils.GetFileAndDirFromPath(filepath)
	isPathExists := ioutils.IsPathExists(dir)
	if !isPathExists {
		os.MkdirAll(dir, 0700)
	}
	err := ioutil.WriteFile(filepath, nil, 0777)
	cliutils.CheckError(err)
}

func saveLicense(filepath string, content []byte){
	if filepath == "" {
		return
	}
	err := ioutil.WriteFile(filepath, content, 0777)
	cliutils.CheckError(err)
}

type AttachLicFlags struct {
	MissionControlDetails *config.MissionControlDetails
	LicensePath 	      string
	NodeId 			      string
	BucketKey 			  string
	BucketId 			  string
	Override 			  bool
	Deploy 			  	  bool
}

type Message struct {
	LicenseKey string `json:"licenseKey,omitempty"`
}

type Data struct {
	Data Message
}
<|endoftext|>


<commit_before>/*
Copyright 2016 The Kubernetes Authors.

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

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

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

package taints

import (
	"reflect"
	"strings"
	"testing"

	"k8s.io/api/core/v1"
	"k8s.io/kubernetes/pkg/api"

	"github.com/spf13/pflag"
)

func TestTaintsVar(t *testing.T) {
	cases := []struct {
		f   string
		err bool
		t   []api.Taint
	}{
		{
			f: "",
			t: []api.Taint(nil),
		},
		{
			f: "--t=foo=bar:NoSchedule",
			t: []api.Taint{{Key: "foo", Value: "bar", Effect: "NoSchedule"}},
		},
		{
			f: "--t=foo=bar:NoSchedule,bing=bang:PreferNoSchedule",
			t: []api.Taint{
				{Key: "foo", Value: "bar", Effect: api.TaintEffectNoSchedule},
				{Key: "bing", Value: "bang", Effect: api.TaintEffectPreferNoSchedule},
			},
		},
		{
			f: "--t=dedicated-for=user1:NoExecute",
			t: []api.Taint{{Key: "dedicated-for", Value: "user1", Effect: "NoExecute"}},
		},
	}

	for i, c := range cases {
		args := append([]string{"test"}, strings.Fields(c.f)...)
		cli := pflag.NewFlagSet("test", pflag.ContinueOnError)
		var taints []api.Taint
		cli.Var(NewTaintsVar(&taints), "t", "bar")

		err := cli.Parse(args)
		if err == nil && c.err {
			t.Errorf("[%v] expected error", i)
			continue
		}
		if err != nil && !c.err {
			t.Errorf("[%v] unexpected error: %v", i, err)
			continue
		}
		if !reflect.DeepEqual(c.t, taints) {
			t.Errorf("[%v] unexpected taints:\n\texpected:\n\t\t%#v\n\tgot:\n\t\t%#v", i, c.t, taints)
		}
	}

}

func TestAddOrUpdateTaint(t *testing.T) {
	node := &v1.Node{}

	taint := &v1.Taint{
		Key:    "foo",
		Value:  "bar",
		Effect: v1.TaintEffectNoSchedule,
	}

	checkResult := func(testCaseName string, newNode *v1.Node, expectedTaint *v1.Taint, result, expectedResult bool, err error) {
		if err != nil {
			t.Errorf("[%s] should not raise error but got %v", testCaseName, err)
		}
		if result != expectedResult {
			t.Errorf("[%s] should return %t, but got: %t", testCaseName, expectedResult, result)
		}
		if len(newNode.Spec.Taints) != 1 || !reflect.DeepEqual(newNode.Spec.Taints[0], *expectedTaint) {
			t.Errorf("[%s] node should only have one taint: %v, but got: %v", testCaseName, *expectedTaint, newNode.Spec.Taints)
		}
	}

	// Add a new Taint.
	newNode, result, err := AddOrUpdateTaint(node, taint)
	checkResult("Add New Taint", newNode, taint, result, true, err)

	// Update a Taint.
	taint.Value = "bar_1"
	newNode, result, err = AddOrUpdateTaint(node, taint)
	checkResult("Update Taint", newNode, taint, result, true, err)

	// Add a duplicate Taint.
	node = newNode
	newNode, result, err = AddOrUpdateTaint(node, taint)
	checkResult("Add Duplicate Taint", newNode, taint, result, false, err)
}

func TestParseTaints(t *testing.T) {
	cases := []struct {
		name                   string
		spec                   []string
		expectedTaints         []v1.Taint
		expectedTaintsToRemove []v1.Taint
		expectedErr            bool
	}{
		{
			name:        "invalid spec format",
			spec:        []string{"foo=abc"},
			expectedErr: true,
		},
		{
			name:        "invalid spec effect for adding taint",
			spec:        []string{"foo=abc:invalid_effect"},
			expectedErr: true,
		},
		{
			name:        "invalid spec effect for deleting taint",
			spec:        []string{"foo:invalid_effect-"},
			expectedErr: true,
		},
		{
			name: "add new taints",
			spec: []string{"foo=abc:NoSchedule", "bar=abc:NoSchedule"},
			expectedTaints: []v1.Taint{
				{
					Key:    "foo",
					Value:  "abc",
					Effect: v1.TaintEffectNoSchedule,
				},
				{
					Key:    "bar",
					Value:  "abc",
					Effect: v1.TaintEffectNoSchedule,
				},
			},
			expectedErr: false,
		},
		{
			name: "delete taints",
			spec: []string{"foo:NoSchedule-", "bar:NoSchedule-"},
			expectedTaintsToRemove: []v1.Taint{
				{
					Key:    "foo",
					Effect: v1.TaintEffectNoSchedule,
				},
				{
					Key:    "bar",
					Effect: v1.TaintEffectNoSchedule,
				},
			},
			expectedErr: false,
		},
		{
			name: "add taints and delete taints",
			spec: []string{"foo=abc:NoSchedule", "bar=abc:NoSchedule", "foo:NoSchedule-", "bar:NoSchedule-"},
			expectedTaints: []v1.Taint{
				{
					Key:    "foo",
					Value:  "abc",
					Effect: v1.TaintEffectNoSchedule,
				},
				{
					Key:    "bar",
					Value:  "abc",
					Effect: v1.TaintEffectNoSchedule,
				},
			},
			expectedTaintsToRemove: []v1.Taint{
				{
					Key:    "foo",
					Effect: v1.TaintEffectNoSchedule,
				},
				{
					Key:    "bar",
					Effect: v1.TaintEffectNoSchedule,
				},
			},
			expectedErr: false,
		},
	}

	for _, c := range cases {
		taints, taintsToRemove, err := ParseTaints(c.spec)
		if c.expectedErr && err == nil {
			t.Errorf("[%s] expected error, but got nothing", c.name)
		}
		if !c.expectedErr && err != nil {
			t.Errorf("[%s] expected no error, but got: %v", c.name, err)
		}
		if !reflect.DeepEqual(c.expectedTaints, taints) {
			t.Errorf("[%s] expected returen taints as %v, but got: %v", c.name, c.expectedTaints, taints)
		}
		if !reflect.DeepEqual(c.expectedTaintsToRemove, taintsToRemove) {
			t.Errorf("[%s] expected return taints to be removed as %v, but got: %v", c.name, c.expectedTaintsToRemove, taintsToRemove)
		}
	}
}
<commit_msg>Added unit test cases for the public methods of pkg/util/taints.go<commit_after>/*
Copyright 2016 The Kubernetes Authors.

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

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

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

package taints

import (
	"reflect"
	"strings"
	"testing"

	"k8s.io/api/core/v1"
	"k8s.io/kubernetes/pkg/api"

	"github.com/spf13/pflag"
)

func TestTaintsVar(t *testing.T) {
	cases := []struct {
		f   string
		err bool
		t   []api.Taint
	}{
		{
			f: "",
			t: []api.Taint(nil),
		},
		{
			f: "--t=foo=bar:NoSchedule",
			t: []api.Taint{{Key: "foo", Value: "bar", Effect: "NoSchedule"}},
		},
		{
			f: "--t=foo=bar:NoSchedule,bing=bang:PreferNoSchedule",
			t: []api.Taint{
				{Key: "foo", Value: "bar", Effect: api.TaintEffectNoSchedule},
				{Key: "bing", Value: "bang", Effect: api.TaintEffectPreferNoSchedule},
			},
		},
		{
			f: "--t=dedicated-for=user1:NoExecute",
			t: []api.Taint{{Key: "dedicated-for", Value: "user1", Effect: "NoExecute"}},
		},
	}

	for i, c := range cases {
		args := append([]string{"test"}, strings.Fields(c.f)...)
		cli := pflag.NewFlagSet("test", pflag.ContinueOnError)
		var taints []api.Taint
		cli.Var(NewTaintsVar(&taints), "t", "bar")

		err := cli.Parse(args)
		if err == nil && c.err {
			t.Errorf("[%v] expected error", i)
			continue
		}
		if err != nil && !c.err {
			t.Errorf("[%v] unexpected error: %v", i, err)
			continue
		}
		if !reflect.DeepEqual(c.t, taints) {
			t.Errorf("[%v] unexpected taints:\n\texpected:\n\t\t%#v\n\tgot:\n\t\t%#v", i, c.t, taints)
		}
	}

}

func TestAddOrUpdateTaint(t *testing.T) {
	node := &v1.Node{}

	taint := &v1.Taint{
		Key:    "foo",
		Value:  "bar",
		Effect: v1.TaintEffectNoSchedule,
	}

	checkResult := func(testCaseName string, newNode *v1.Node, expectedTaint *v1.Taint, result, expectedResult bool, err error) {
		if err != nil {
			t.Errorf("[%s] should not raise error but got %v", testCaseName, err)
		}
		if result != expectedResult {
			t.Errorf("[%s] should return %t, but got: %t", testCaseName, expectedResult, result)
		}
		if len(newNode.Spec.Taints) != 1 || !reflect.DeepEqual(newNode.Spec.Taints[0], *expectedTaint) {
			t.Errorf("[%s] node should only have one taint: %v, but got: %v", testCaseName, *expectedTaint, newNode.Spec.Taints)
		}
	}

	// Add a new Taint.
	newNode, result, err := AddOrUpdateTaint(node, taint)
	checkResult("Add New Taint", newNode, taint, result, true, err)

	// Update a Taint.
	taint.Value = "bar_1"
	newNode, result, err = AddOrUpdateTaint(node, taint)
	checkResult("Update Taint", newNode, taint, result, true, err)

	// Add a duplicate Taint.
	node = newNode
	newNode, result, err = AddOrUpdateTaint(node, taint)
	checkResult("Add Duplicate Taint", newNode, taint, result, false, err)
}

func TestTaintExists(t *testing.T) {
	testingTaints := []v1.Taint{
		{
			Key:    "foo_1",
			Value:  "bar_1",
			Effect: v1.TaintEffectNoExecute,
		},
		{
			Key:    "foo_2",
			Value:  "bar_2",
			Effect: v1.TaintEffectNoSchedule,
		},
	}

	cases := []struct {
		name           string
		taintToFind    *v1.Taint
		expectedResult bool
	}{
		{
			name:           "taint exists",
			taintToFind:    &v1.Taint{Key: "foo_1", Value: "bar_1", Effect: v1.TaintEffectNoExecute},
			expectedResult: true,
		},
		{
			name:           "different key",
			taintToFind:    &v1.Taint{Key: "no_such_key", Value: "bar_1", Effect: v1.TaintEffectNoExecute},
			expectedResult: false,
		},
		{
			name:           "different effect",
			taintToFind:    &v1.Taint{Key: "foo_1", Value: "bar_1", Effect: v1.TaintEffectNoSchedule},
			expectedResult: false,
		},
	}

	for _, c := range cases {
		result := TaintExists(testingTaints, c.taintToFind)

		if result != c.expectedResult {
			t.Errorf("[%s] unexpected results: %v", c.name, result)
			continue
		}
	}
}

func TestRemoveTaint(t *testing.T) {
	cases := []struct {
		name           string
		node           *v1.Node
		taintToRemove  *v1.Taint
		expectedTaints []v1.Taint
		expectedResult bool
	}{
		{
			name: "remove taint unsuccessfully",
			node: &v1.Node{
				Spec: v1.NodeSpec{
					Taints: []v1.Taint{
						{
							Key:    "foo",
							Effect: v1.TaintEffectNoSchedule,
						},
					},
				},
			},
			taintToRemove: &v1.Taint{
				Key:    "foo_1",
				Effect: v1.TaintEffectNoSchedule,
			},
			expectedTaints: []v1.Taint{
				{
					Key:    "foo",
					Effect: v1.TaintEffectNoSchedule,
				},
			},
			expectedResult: false,
		},
		{
			name: "remove taint successfully",
			node: &v1.Node{
				Spec: v1.NodeSpec{
					Taints: []v1.Taint{
						{
							Key:    "foo",
							Effect: v1.TaintEffectNoSchedule,
						},
					},
				},
			},
			taintToRemove: &v1.Taint{
				Key:    "foo",
				Effect: v1.TaintEffectNoSchedule,
			},
			expectedTaints: []v1.Taint{},
			expectedResult: true,
		},
		{
			name: "remove taint from node with no taint",
			node: &v1.Node{
				Spec: v1.NodeSpec{
					Taints: []v1.Taint{},
				},
			},
			taintToRemove: &v1.Taint{
				Key:    "foo",
				Effect: v1.TaintEffectNoSchedule,
			},
			expectedTaints: []v1.Taint{},
			expectedResult: false,
		},
	}

	for _, c := range cases {
		newNode, result, err := RemoveTaint(c.node, c.taintToRemove)
		if err != nil {
			t.Errorf("[%s] should not raise error but got: %v", c.name, err)
		}
		if result != c.expectedResult {
			t.Errorf("[%s] should return %t, but got: %t", c.name, c.expectedResult, result)
		}
		if !reflect.DeepEqual(newNode.Spec.Taints, c.expectedTaints) {
			t.Errorf("[%s] the new node object should have taints %v, but got: %v", c.name, c.expectedTaints, newNode.Spec.Taints)
		}
	}
}

func TestDeleteTaint(t *testing.T) {
	cases := []struct {
		name           string
		taints         []v1.Taint
		taintToDelete  *v1.Taint
		expectedTaints []v1.Taint
		expectedResult bool
	}{
		{
			name: "delete taint with different name",
			taints: []v1.Taint{
				{
					Key:    "foo",
					Effect: v1.TaintEffectNoSchedule,
				},
			},
			taintToDelete: &v1.Taint{Key: "foo_1", Effect: v1.TaintEffectNoSchedule},
			expectedTaints: []v1.Taint{
				{
					Key:    "foo",
					Effect: v1.TaintEffectNoSchedule,
				},
			},
			expectedResult: false,
		},
		{
			name: "delete taint with different effect",
			taints: []v1.Taint{
				{
					Key:    "foo",
					Effect: v1.TaintEffectNoSchedule,
				},
			},
			taintToDelete: &v1.Taint{Key: "foo", Effect: v1.TaintEffectNoExecute},
			expectedTaints: []v1.Taint{
				{
					Key:    "foo",
					Effect: v1.TaintEffectNoSchedule,
				},
			},
			expectedResult: false,
		},
		{
			name: "delete taint successfully",
			taints: []v1.Taint{
				{
					Key:    "foo",
					Effect: v1.TaintEffectNoSchedule,
				},
			},
			taintToDelete:  &v1.Taint{Key: "foo", Effect: v1.TaintEffectNoSchedule},
			expectedTaints: []v1.Taint{},
			expectedResult: true,
		},
		{
			name:           "delete taint from empty taint array",
			taints:         []v1.Taint{},
			taintToDelete:  &v1.Taint{Key: "foo", Effect: v1.TaintEffectNoSchedule},
			expectedTaints: []v1.Taint{},
			expectedResult: false,
		},
	}

	for _, c := range cases {
		taints, result := DeleteTaint(c.taints, c.taintToDelete)
		if result != c.expectedResult {
			t.Errorf("[%s] should return %t, but got: %t", c.name, c.expectedResult, result)
		}
		if !reflect.DeepEqual(taints, c.expectedTaints) {
			t.Errorf("[%s] the result taints should be %v, but got: %v", c.name, c.expectedTaints, taints)
		}
	}
}

func TestDeleteTaintByKey(t *testing.T) {
	cases := []struct {
		name           string
		taints         []v1.Taint
		taintKey       string
		expectedTaints []v1.Taint
		expectedResult bool
	}{
		{
			name: "delete taint unsuccessfully",
			taints: []v1.Taint{
				{
					Key:    "foo",
					Value:  "bar",
					Effect: v1.TaintEffectNoSchedule,
				},
			},
			taintKey: "foo_1",
			expectedTaints: []v1.Taint{
				{
					Key:    "foo",
					Value:  "bar",
					Effect: v1.TaintEffectNoSchedule,
				},
			},
			expectedResult: false,
		},
		{
			name: "delete taint successfully",
			taints: []v1.Taint{
				{
					Key:    "foo",
					Value:  "bar",
					Effect: v1.TaintEffectNoSchedule,
				},
			},
			taintKey:       "foo",
			expectedTaints: []v1.Taint{},
			expectedResult: true,
		},
		{
			name:           "delete taint from empty taint array",
			taints:         []v1.Taint{},
			taintKey:       "foo",
			expectedTaints: []v1.Taint{},
			expectedResult: false,
		},
	}

	for _, c := range cases {
		taints, result := DeleteTaintsByKey(c.taints, c.taintKey)
		if result != c.expectedResult {
			t.Errorf("[%s] should return %t, but got: %t", c.name, c.expectedResult, result)
		}
		if !reflect.DeepEqual(c.expectedTaints, taints) {
			t.Errorf("[%s] the result taints should be %v, but got: %v", c.name, c.expectedTaints, taints)
		}
	}
}

func TestCheckIfTaintsAlreadyExists(t *testing.T) {
	oldTaints := []v1.Taint{
		{
			Key:    "foo_1",
			Value:  "bar",
			Effect: v1.TaintEffectNoSchedule,
		},
		{
			Key:    "foo_2",
			Value:  "bar",
			Effect: v1.TaintEffectNoSchedule,
		},
		{
			Key:    "foo_3",
			Value:  "bar",
			Effect: v1.TaintEffectNoSchedule,
		},
	}

	cases := []struct {
		name           string
		taintsToCheck  []v1.Taint
		expectedResult string
	}{
		{
			name:           "empty array",
			taintsToCheck:  []v1.Taint{},
			expectedResult: "",
		},
		{
			name: "no match",
			taintsToCheck: []v1.Taint{
				{
					Key:    "foo_1",
					Effect: v1.TaintEffectNoExecute,
				},
			},
			expectedResult: "",
		},
		{
			name: "match one taint",
			taintsToCheck: []v1.Taint{
				{
					Key:    "foo_2",
					Effect: v1.TaintEffectNoSchedule,
				},
			},
			expectedResult: "foo_2",
		},
		{
			name: "match two taints",
			taintsToCheck: []v1.Taint{
				{
					Key:    "foo_2",
					Effect: v1.TaintEffectNoSchedule,
				},
				{
					Key:    "foo_3",
					Effect: v1.TaintEffectNoSchedule,
				},
			},
			expectedResult: "foo_2,foo_3",
		},
	}

	for _, c := range cases {
		result := CheckIfTaintsAlreadyExists(oldTaints, c.taintsToCheck)
		if result != c.expectedResult {
			t.Errorf("[%s] should return '%s', but got: '%s'", c.name, c.expectedResult, result)
		}
	}
}

func TestReorganizeTaints(t *testing.T) {
	node := &v1.Node{
		Spec: v1.NodeSpec{
			Taints: []v1.Taint{
				{
					Key:    "foo",
					Value:  "bar",
					Effect: v1.TaintEffectNoSchedule,
				},
			},
		},
	}

	cases := []struct {
		name              string
		overwrite         bool
		taintsToAdd       []v1.Taint
		taintsToDelete    []v1.Taint
		expectedTaints    []v1.Taint
		expectedOperation string
		expectedErr       bool
	}{
		{
			name:              "no changes with overwrite is true",
			overwrite:         true,
			taintsToAdd:       []v1.Taint{},
			taintsToDelete:    []v1.Taint{},
			expectedTaints:    node.Spec.Taints,
			expectedOperation: MODIFIED,
			expectedErr:       false,
		},
		{
			name:              "no changes with overwrite is false",
			overwrite:         false,
			taintsToAdd:       []v1.Taint{},
			taintsToDelete:    []v1.Taint{},
			expectedTaints:    node.Spec.Taints,
			expectedOperation: UNTAINTED,
			expectedErr:       false,
		},
		{
			name:      "add new taint",
			overwrite: false,
			taintsToAdd: []v1.Taint{
				{
					Key:    "foo_1",
					Effect: v1.TaintEffectNoExecute,
				},
			},
			taintsToDelete:    []v1.Taint{},
			expectedTaints:    append([]v1.Taint{{Key: "foo_1", Effect: v1.TaintEffectNoExecute}}, node.Spec.Taints...),
			expectedOperation: TAINTED,
			expectedErr:       false,
		},
		{
			name:        "delete taint with effect",
			overwrite:   false,
			taintsToAdd: []v1.Taint{},
			taintsToDelete: []v1.Taint{
				{
					Key:    "foo",
					Effect: v1.TaintEffectNoSchedule,
				},
			},
			expectedTaints:    []v1.Taint{},
			expectedOperation: UNTAINTED,
			expectedErr:       false,
		},
		{
			name:        "delete taint with no effect",
			overwrite:   false,
			taintsToAdd: []v1.Taint{},
			taintsToDelete: []v1.Taint{
				{
					Key: "foo",
				},
			},
			expectedTaints:    []v1.Taint{},
			expectedOperation: UNTAINTED,
			expectedErr:       false,
		},
		{
			name:        "delete non-exist taint",
			overwrite:   false,
			taintsToAdd: []v1.Taint{},
			taintsToDelete: []v1.Taint{
				{
					Key:    "foo_1",
					Effect: v1.TaintEffectNoSchedule,
				},
			},
			expectedTaints:    node.Spec.Taints,
			expectedOperation: UNTAINTED,
			expectedErr:       true,
		},
		{
			name:      "add new taint and delete old one",
			overwrite: false,
			taintsToAdd: []v1.Taint{
				{
					Key:    "foo_1",
					Effect: v1.TaintEffectNoSchedule,
				},
			},
			taintsToDelete: []v1.Taint{
				{
					Key:    "foo",
					Effect: v1.TaintEffectNoSchedule,
				},
			},
			expectedTaints: []v1.Taint{
				{
					Key:    "foo_1",
					Effect: v1.TaintEffectNoSchedule,
				},
			},
			expectedOperation: MODIFIED,
			expectedErr:       false,
		},
	}

	for _, c := range cases {
		operation, taints, err := ReorganizeTaints(node, c.overwrite, c.taintsToAdd, c.taintsToDelete)
		if c.expectedErr && err == nil {
			t.Errorf("[%s] expect to see an error, but did not get one", c.name)
		} else if !c.expectedErr && err != nil {
			t.Errorf("[%s] expect not to see an error, but got one: %v", c.name, err)
		}

		if !reflect.DeepEqual(c.expectedTaints, taints) {
			t.Errorf("[%s] expect to see taint list %#v, but got: %#v", c.name, c.expectedTaints, taints)
		}

		if c.expectedOperation != operation {
			t.Errorf("[%s] expect to see operation %s, but got: %s", c.name, c.expectedOperation, operation)
		}
	}
}

func TestParseTaints(t *testing.T) {
	cases := []struct {
		name                   string
		spec                   []string
		expectedTaints         []v1.Taint
		expectedTaintsToRemove []v1.Taint
		expectedErr            bool
	}{
		{
			name:        "invalid spec format",
			spec:        []string{"foo=abc"},
			expectedErr: true,
		},
		{
			name:        "invalid spec effect for adding taint",
			spec:        []string{"foo=abc:invalid_effect"},
			expectedErr: true,
		},
		{
			name:        "invalid spec effect for deleting taint",
			spec:        []string{"foo:invalid_effect-"},
			expectedErr: true,
		},
		{
			name: "add new taints",
			spec: []string{"foo=abc:NoSchedule", "bar=abc:NoSchedule"},
			expectedTaints: []v1.Taint{
				{
					Key:    "foo",
					Value:  "abc",
					Effect: v1.TaintEffectNoSchedule,
				},
				{
					Key:    "bar",
					Value:  "abc",
					Effect: v1.TaintEffectNoSchedule,
				},
			},
			expectedErr: false,
		},
		{
			name: "delete taints",
			spec: []string{"foo:NoSchedule-", "bar:NoSchedule-"},
			expectedTaintsToRemove: []v1.Taint{
				{
					Key:    "foo",
					Effect: v1.TaintEffectNoSchedule,
				},
				{
					Key:    "bar",
					Effect: v1.TaintEffectNoSchedule,
				},
			},
			expectedErr: false,
		},
		{
			name: "add taints and delete taints",
			spec: []string{"foo=abc:NoSchedule", "bar=abc:NoSchedule", "foo:NoSchedule-", "bar:NoSchedule-"},
			expectedTaints: []v1.Taint{
				{
					Key:    "foo",
					Value:  "abc",
					Effect: v1.TaintEffectNoSchedule,
				},
				{
					Key:    "bar",
					Value:  "abc",
					Effect: v1.TaintEffectNoSchedule,
				},
			},
			expectedTaintsToRemove: []v1.Taint{
				{
					Key:    "foo",
					Effect: v1.TaintEffectNoSchedule,
				},
				{
					Key:    "bar",
					Effect: v1.TaintEffectNoSchedule,
				},
			},
			expectedErr: false,
		},
	}

	for _, c := range cases {
		taints, taintsToRemove, err := ParseTaints(c.spec)
		if c.expectedErr && err == nil {
			t.Errorf("[%s] expected error, but got nothing", c.name)
		}
		if !c.expectedErr && err != nil {
			t.Errorf("[%s] expected no error, but got: %v", c.name, err)
		}
		if !reflect.DeepEqual(c.expectedTaints, taints) {
			t.Errorf("[%s] expected returen taints as %v, but got: %v", c.name, c.expectedTaints, taints)
		}
		if !reflect.DeepEqual(c.expectedTaintsToRemove, taintsToRemove) {
			t.Errorf("[%s] expected return taints to be removed as %v, but got: %v", c.name, c.expectedTaintsToRemove, taintsToRemove)
		}
	}
}
<|endoftext|>


<commit_before><commit_msg>Add tests for new VerifyTenantMounts method<commit_after><|endoftext|>


<commit_before>// Copyright 2015 Lukas Weber. All rights reserved.
// Use of this source code is governed by the MIT-styled
// license that can be found in the LICENSE file.

package main

import (
	"bufio"
	"bytes"
	"errors"
	"net/textproto"
	"os"
	"os/exec"
	"strings"
	"time"

	"github.com/nsf/termbox-go"
)

// ComposeBuffer is a MailBuffer that allows editing and sending the viewed message.
type ComposeBuffer struct {
	mb   *MailBuffer
	sent bool
}

// NewComposeBuffer creates a new Composebuffer for displaying a mail.
func NewComposeBuffer(m *Mail) *ComposeBuffer {
	return &ComposeBuffer{NewMailBufferFromMail(m), false}
}

// Draw draws the buffer content.
func (b *ComposeBuffer) Draw() {
	b.mb.Draw()
}

// Title returns the buffer's title string.
func (b *ComposeBuffer) Title() string {
	if b.sent {
		return "sent"
	} else {
		return "unsent"
	}
}

// Name returns the buffer's name.
func (b *ComposeBuffer) Name() string {
	return "compose"
}

// Close closes the buffer.
func (b *ComposeBuffer) Close() {
	b.mb.Close()
}

// writeEditString writes an editable version of a mail consisting of a
// header paragraph containing some of the mails headers and the message body.
//
// The format is as follows:
//
//	Header1: value
//	Header2: value
//	Header3: value
//
//	Hi,
//	This is the message body text.
func writeEditString(filename string, m *Mail) error {
	file, err := os.Create(filename)
	if err != nil {
		return err
	}
	defer file.Close()

	file.Write([]byte("From: " + m.Header.Get("From") + "\n"))
	file.Write([]byte("To: " + m.Header.Get("To") + "\n"))
	file.Write([]byte("Subject: " + m.Header.Get("Subject") + "\n"))
	file.Write([]byte{'\n'})

	// assume the first part exists, is text/plain, and contains the message body.
	if len(m.Parts) == 0 {
		h := make(textproto.MIMEHeader)
		h["Content-Type"] = []string{"text/plain; charset=\"utf-8\""}
		h["Content-Transfer-Encoding"] = []string{"quoted-printable"}
		m.Parts = append(m.Parts, Part{h, ""})
	}
	file.Write([]byte(m.Parts[0].Body))
	return nil
}

// parseEditString parses a string created by writeEditString and edited by the user.
// it updates the changed header flags and message body.
func parseEditString(filename string, m *Mail) error {
	file, err := os.Open(filename)
	if err != nil {
		return err
	}
	defer file.Close()
	var buf bytes.Buffer

	scanner := bufio.NewScanner(file)
	scanHeaders := true
	for scanner.Scan() {
		if len(scanner.Bytes()) == 0 && scanHeaders {
			scanHeaders = false // don't scan headers after new line.
			continue
		}
		if scanHeaders {
			toks := strings.SplitN(scanner.Text(), ":", 2)
			if len(toks) != 2 {
				return errors.New("Error: invalid header section.")
			}
			m.Header[strings.TrimSpace(toks[0])] =
				[]string{strings.TrimSpace(toks[1])}
		} else {
			_, err := buf.WriteString(scanner.Text() + "\n")
			if err != nil {
				return err
			}
		}
	}
	if err := scanner.Err(); err != nil {
		return err
	}

	if len(m.Parts) == 0 {
		return errors.New("Error: editing invalid mail.")
	}
	m.Parts[0].Body = buf.String()
	return nil
}

func (b *ComposeBuffer) openEditor(stack *BufferStack) {
	filename := b.mb.tmpDir + "/edit.eml"

	err := writeEditString(filename, b.mb.mail)
	if err != nil {
		StatusLine = err.Error()
		return
	}

	termbox.Close()
	cmd := exec.Command(config.Commands.Editor, filename)
	cmd.Stdin = os.Stdin
	cmd.Stdout = os.Stdout
	err = cmd.Run()
	if err != nil {
		StatusLine = err.Error()
	}
	termbox.Init()
	termbox.Sync()
	err = parseEditString(filename, b.mb.mail)
	if err != nil {
		StatusLine = err.Error()
	}
	b.mb.mail.Header["Date"] = []string{time.Now().Format(time.RFC1123Z)}
	b.mb.refreshBuf()
	stack.refresh()
}

// HandleCommand executes buffer local commands.
func (b *ComposeBuffer) HandleCommand(cmd string, args []string, stack *BufferStack) bool {
	switch cmd {
	case "reply", "raw": // disallow invalid commands in compose mode
	case "edit":
		b.openEditor(stack)
	case "send":
		if b.sent {
			StatusLine = "Mail already sent"
			break
		}
		StatusLine = "Sending..."
		stack.refresh()
		err := sendMail(b.mb.mail)
		if err != nil {
			StatusLine = err.Error()
		} else {
			StatusLine = "Mail sent."
		}
	case "attach":
		if len(args) == 0 {
			StatusLine = "Nothing to attach"
			break
		}

		err := b.mb.mail.attachFile(expandEnvHome(strings.Join(args, " ")))
		if err != nil {
			StatusLine = err.Error()
		} else {
			StatusLine = "attached \"" + strings.Join(args, " ") + "\""
		}
		b.mb.refreshBuf()
		b.Draw()
	case "deattach":
		if len(b.mb.mail.Parts) > 1 {
			b.mb.mail.Parts = b.mb.mail.Parts[:len(b.mb.mail.Parts)-1]
		}
		StatusLine = "deattached attachment"
		b.mb.refreshBuf()
		b.Draw()
	default:
		return b.mb.HandleCommand(cmd, args, stack)
	}
	return true
}
<commit_msg>actually update the sent indicator<commit_after>// Copyright 2015 Lukas Weber. All rights reserved.
// Use of this source code is governed by the MIT-styled
// license that can be found in the LICENSE file.

package main

import (
	"bufio"
	"bytes"
	"errors"
	"net/textproto"
	"os"
	"os/exec"
	"strings"
	"time"

	"github.com/nsf/termbox-go"
)

// ComposeBuffer is a MailBuffer that allows editing and sending the viewed message.
type ComposeBuffer struct {
	mb   *MailBuffer
	sent bool
}

// NewComposeBuffer creates a new Composebuffer for displaying a mail.
func NewComposeBuffer(m *Mail) *ComposeBuffer {
	return &ComposeBuffer{NewMailBufferFromMail(m), false}
}

// Draw draws the buffer content.
func (b *ComposeBuffer) Draw() {
	b.mb.Draw()
}

// Title returns the buffer's title string.
func (b *ComposeBuffer) Title() string {
	if b.sent {
		return "sent"
	} else {
		return "unsent"
	}
}

// Name returns the buffer's name.
func (b *ComposeBuffer) Name() string {
	return "compose"
}

// Close closes the buffer.
func (b *ComposeBuffer) Close() {
	b.mb.Close()
}

// writeEditString writes an editable version of a mail consisting of a
// header paragraph containing some of the mails headers and the message body.
//
// The format is as follows:
//
//	Header1: value
//	Header2: value
//	Header3: value
//
//	Hi,
//	This is the message body text.
func writeEditString(filename string, m *Mail) error {
	file, err := os.Create(filename)
	if err != nil {
		return err
	}
	defer file.Close()

	file.Write([]byte("From: " + m.Header.Get("From") + "\n"))
	file.Write([]byte("To: " + m.Header.Get("To") + "\n"))
	file.Write([]byte("Subject: " + m.Header.Get("Subject") + "\n"))
	file.Write([]byte{'\n'})

	// assume the first part exists, is text/plain, and contains the message body.
	if len(m.Parts) == 0 {
		h := make(textproto.MIMEHeader)
		h["Content-Type"] = []string{"text/plain; charset=\"utf-8\""}
		h["Content-Transfer-Encoding"] = []string{"quoted-printable"}
		m.Parts = append(m.Parts, Part{h, ""})
	}
	file.Write([]byte(m.Parts[0].Body))
	return nil
}

// parseEditString parses a string created by writeEditString and edited by the user.
// it updates the changed header flags and message body.
func parseEditString(filename string, m *Mail) error {
	file, err := os.Open(filename)
	if err != nil {
		return err
	}
	defer file.Close()
	var buf bytes.Buffer

	scanner := bufio.NewScanner(file)
	scanHeaders := true
	for scanner.Scan() {
		if len(scanner.Bytes()) == 0 && scanHeaders {
			scanHeaders = false // don't scan headers after new line.
			continue
		}
		if scanHeaders {
			toks := strings.SplitN(scanner.Text(), ":", 2)
			if len(toks) != 2 {
				return errors.New("Error: invalid header section.")
			}
			m.Header[strings.TrimSpace(toks[0])] =
				[]string{strings.TrimSpace(toks[1])}
		} else {
			_, err := buf.WriteString(scanner.Text() + "\n")
			if err != nil {
				return err
			}
		}
	}
	if err := scanner.Err(); err != nil {
		return err
	}

	if len(m.Parts) == 0 {
		return errors.New("Error: editing invalid mail.")
	}
	m.Parts[0].Body = buf.String()
	return nil
}

func (b *ComposeBuffer) openEditor(stack *BufferStack) {
	filename := b.mb.tmpDir + "/edit.eml"

	err := writeEditString(filename, b.mb.mail)
	if err != nil {
		StatusLine = err.Error()
		return
	}

	termbox.Close()
	cmd := exec.Command(config.Commands.Editor, filename)
	cmd.Stdin = os.Stdin
	cmd.Stdout = os.Stdout
	err = cmd.Run()
	if err != nil {
		StatusLine = err.Error()
	}
	termbox.Init()
	termbox.Sync()
	err = parseEditString(filename, b.mb.mail)
	if err != nil {
		StatusLine = err.Error()
	}
	b.mb.mail.Header["Date"] = []string{time.Now().Format(time.RFC1123Z)}
	b.mb.refreshBuf()
	stack.refresh()
}

// HandleCommand executes buffer local commands.
func (b *ComposeBuffer) HandleCommand(cmd string, args []string, stack *BufferStack) bool {
	switch cmd {
	case "reply", "raw": // disallow invalid commands in compose mode
	case "edit":
		b.openEditor(stack)
	case "send":
		if b.sent {
			StatusLine = "Mail already sent"
			break
		}
		StatusLine = "Sending..."
		stack.refresh()
		err := sendMail(b.mb.mail)
		if err != nil {
			StatusLine = err.Error()
		} else {
			StatusLine = "Mail sent."
			b.sent = true
		}
	case "attach":
		if len(args) == 0 {
			StatusLine = "Nothing to attach"
			break
		}

		err := b.mb.mail.attachFile(expandEnvHome(strings.Join(args, " ")))
		if err != nil {
			StatusLine = err.Error()
		} else {
			StatusLine = "attached \"" + strings.Join(args, " ") + "\""
		}
		b.mb.refreshBuf()
		b.Draw()
	case "deattach":
		if len(b.mb.mail.Parts) > 1 {
			b.mb.mail.Parts = b.mb.mail.Parts[:len(b.mb.mail.Parts)-1]
		}
		StatusLine = "deattached attachment"
		b.mb.refreshBuf()
		b.Draw()
	default:
		return b.mb.HandleCommand(cmd, args, stack)
	}
	return true
}
<|endoftext|>


<commit_before>// Copyright 2015 Keybase, Inc. All rights reserved. Use of
// this source code is governed by the included BSD license.

package keybase

import (
	"encoding/base64"
	"errors"
	"fmt"
	"net"
	"sync"

	"github.com/keybase/client/go/libkb"
	"github.com/keybase/client/go/logger"
	"github.com/keybase/client/go/protocol"
	"github.com/keybase/client/go/service"
	"github.com/keybase/go-framed-msgpack-rpc"
	"github.com/keybase/kbfs/fsrpc"
	"github.com/keybase/kbfs/libkbfs"
)

var kbCtx *libkb.GlobalContext
var conn net.Conn
var startOnce sync.Once
var logSendContext libkb.LogSendContext
var kbfsConfig libkbfs.Config

// InitOnce runs the Keybase services (only runs one time)
func InitOnce(homeDir string, logFile string, runModeStr string, accessGroupOverride bool) {
	startOnce.Do(func() {
		if err := Init(homeDir, logFile, runModeStr, accessGroupOverride); err != nil {
			kbCtx.Log.Errorf("Init error: %s", err)
		}
	})
}

// Init runs the Keybase services
func Init(homeDir string, logFile string, runModeStr string, accessGroupOverride bool) error {
	fmt.Println("Go: Initializing")
	fmt.Printf("Go: Using log: %s\n", logFile)
	kbCtx = libkb.G
	kbCtx.Init()
	usage := libkb.Usage{
		Config:    true,
		API:       true,
		KbKeyring: true,
	}
	runMode, err := libkb.StringToRunMode(runModeStr)
	if err != nil {
		return err
	}
	config := libkb.AppConfig{
		HomeDir:                     homeDir,
		LogFile:                     logFile,
		RunMode:                     runMode,
		Debug:                       true,
		LocalRPCDebug:               "Acsvip",
		SecurityAccessGroupOverride: accessGroupOverride,
	}
	err = kbCtx.Configure(config, usage)
	if err != nil {
		return err
	}

	svc := service.NewService(kbCtx, false)
	svc.StartLoopbackServer()
	kbCtx.SetService()
	kbCtx.SetUIRouter(service.NewUIRouter(kbCtx))

	serviceLog := config.GetLogFile()
	logs := libkb.Logs{
		Service: serviceLog,
	}

	logSendContext = libkb.LogSendContext{
		Contextified: libkb.NewContextified(kbCtx),
		Logs:         logs,
	}

	kbfsParams := libkbfs.DefaultInitParams(kbCtx)
	kbfsConfig, err = libkbfs.Init(kbCtx, kbfsParams, newKeybaseDaemon, func() {}, kbCtx.Log)
	if err != nil {
		return err
	}

	return Reset()
}

func newKeybaseDaemon(config libkbfs.Config, params libkbfs.InitParams, ctx libkbfs.Context, log logger.Logger) (libkbfs.KeybaseDaemon, error) {
	keybaseDaemon := libkbfs.NewKeybaseDaemonRPC(config, ctx, log, true)
	keybaseDaemon.AddProtocols([]rpc.Protocol{
		keybase1.FsProtocol(fsrpc.NewFS(config, log)),
	})
	return keybaseDaemon, nil
}

// LogSend sends a log to Keybase
func LogSend(uiLogPath string) (string, error) {
	logSendContext.Logs.Desktop = uiLogPath
	return logSendContext.LogSend("", 10000)
}

// WriteB64 sends a base64 encoded msgpack rpc payload
func WriteB64(str string) error {
	data, err := base64.StdEncoding.DecodeString(str)
	if err != nil {
		return fmt.Errorf("Base64 decode error: %s; %s", err, str)
	}
	n, err := conn.Write(data)
	if err != nil {
		return fmt.Errorf("Write error: %s", err)
	}
	if n != len(data) {
		return errors.New("Did not write all the data")
	}
	return nil
}

const targetBufferSize = 50 * 1024

// bufferSize must be divisible by 3 to ensure that we don't split
// our b64 encode across a payload boundary if we go over our buffer
// size.
const bufferSize = targetBufferSize - (targetBufferSize % 3)

// ReadB64 is a blocking read for base64 encoded msgpack rpc data.
func ReadB64() (string, error) {
	data := make([]byte, bufferSize)

	n, err := conn.Read(data)
	if n > 0 && err == nil {
		str := base64.StdEncoding.EncodeToString(data[0:n])
		return str, nil
	}

	if err != nil {
		// Attempt to fix the connection
		Reset()
		return "", fmt.Errorf("Read error: %s", err)
	}

	return "", nil
}

// Reset resets the socket connection
func Reset() error {
	if conn != nil {
		conn.Close()
	}

	var err error
	conn, _, _, err = kbCtx.ResetSocket(false)
	if err != nil {
		return fmt.Errorf("Socket error: %s", err)
	}
	return nil
}
<commit_msg>Comment out libkbfs.Init in mobile due to RPC issue<commit_after>// Copyright 2015 Keybase, Inc. All rights reserved. Use of
// this source code is governed by the included BSD license.

package keybase

import (
	"encoding/base64"
	"errors"
	"fmt"
	"net"
	"sync"

	"github.com/keybase/client/go/libkb"
	"github.com/keybase/client/go/logger"
	"github.com/keybase/client/go/protocol"
	"github.com/keybase/client/go/service"
	"github.com/keybase/go-framed-msgpack-rpc"
	"github.com/keybase/kbfs/fsrpc"
	"github.com/keybase/kbfs/libkbfs"
)

var kbCtx *libkb.GlobalContext
var conn net.Conn
var startOnce sync.Once
var logSendContext libkb.LogSendContext
var kbfsConfig libkbfs.Config

// InitOnce runs the Keybase services (only runs one time)
func InitOnce(homeDir string, logFile string, runModeStr string, accessGroupOverride bool) {
	startOnce.Do(func() {
		if err := Init(homeDir, logFile, runModeStr, accessGroupOverride); err != nil {
			kbCtx.Log.Errorf("Init error: %s", err)
		}
	})
}

// Init runs the Keybase services
func Init(homeDir string, logFile string, runModeStr string, accessGroupOverride bool) error {
	fmt.Println("Go: Initializing")
	fmt.Printf("Go: Using log: %s\n", logFile)
	kbCtx = libkb.G
	kbCtx.Init()
	usage := libkb.Usage{
		Config:    true,
		API:       true,
		KbKeyring: true,
	}
	runMode, err := libkb.StringToRunMode(runModeStr)
	if err != nil {
		return err
	}
	config := libkb.AppConfig{
		HomeDir:                     homeDir,
		LogFile:                     logFile,
		RunMode:                     runMode,
		Debug:                       true,
		LocalRPCDebug:               "Acsvip",
		SecurityAccessGroupOverride: accessGroupOverride,
	}
	err = kbCtx.Configure(config, usage)
	if err != nil {
		return err
	}

	svc := service.NewService(kbCtx, false)
	svc.StartLoopbackServer()
	kbCtx.SetService()
	kbCtx.SetUIRouter(service.NewUIRouter(kbCtx))

	serviceLog := config.GetLogFile()
	logs := libkb.Logs{
		Service: serviceLog,
	}

	logSendContext = libkb.LogSendContext{
		Contextified: libkb.NewContextified(kbCtx),
		Logs:         logs,
	}

	// FIXME (MBG): This is causing RPC responses to sometimes not be recieved
	// on iOS. Repro by hooking up getExtendedStatus to a button in the iOS
	// client and watching JS logs. Disabling until we have a root cause / fix.
	//
	//kbfsParams := libkbfs.DefaultInitParams(kbCtx)
	//kbfsConfig, err = libkbfs.Init(kbCtx, kbfsParams, newKeybaseDaemon, func() {}, kbCtx.Log)
	//if err != nil {
	//	return err
	//}

	return Reset()
}

func newKeybaseDaemon(config libkbfs.Config, params libkbfs.InitParams, ctx libkbfs.Context, log logger.Logger) (libkbfs.KeybaseDaemon, error) {
	keybaseDaemon := libkbfs.NewKeybaseDaemonRPC(config, ctx, log, true)
	keybaseDaemon.AddProtocols([]rpc.Protocol{
		keybase1.FsProtocol(fsrpc.NewFS(config, log)),
	})
	return keybaseDaemon, nil
}

// LogSend sends a log to Keybase
func LogSend(uiLogPath string) (string, error) {
	logSendContext.Logs.Desktop = uiLogPath
	return logSendContext.LogSend("", 10000)
}

// WriteB64 sends a base64 encoded msgpack rpc payload
func WriteB64(str string) error {
	data, err := base64.StdEncoding.DecodeString(str)
	if err != nil {
		return fmt.Errorf("Base64 decode error: %s; %s", err, str)
	}
	n, err := conn.Write(data)
	if err != nil {
		return fmt.Errorf("Write error: %s", err)
	}
	if n != len(data) {
		return errors.New("Did not write all the data")
	}
	return nil
}

const targetBufferSize = 50 * 1024

// bufferSize must be divisible by 3 to ensure that we don't split
// our b64 encode across a payload boundary if we go over our buffer
// size.
const bufferSize = targetBufferSize - (targetBufferSize % 3)

// ReadB64 is a blocking read for base64 encoded msgpack rpc data.
func ReadB64() (string, error) {
	data := make([]byte, bufferSize)

	n, err := conn.Read(data)
	if n > 0 && err == nil {
		str := base64.StdEncoding.EncodeToString(data[0:n])
		return str, nil
	}

	if err != nil {
		// Attempt to fix the connection
		Reset()
		return "", fmt.Errorf("Read error: %s", err)
	}

	return "", nil
}

// Reset resets the socket connection
func Reset() error {
	if conn != nil {
		conn.Close()
	}

	var err error
	conn, _, _, err = kbCtx.ResetSocket(false)
	if err != nil {
		return fmt.Errorf("Socket error: %s", err)
	}
	return nil
}
<|endoftext|>


<commit_before>// Copyright 2015 Keybase, Inc. All rights reserved. Use of
// this source code is governed by the included BSD license.

package keybase

import (
	"encoding/base64"
	"errors"
	"fmt"
	"net"
	"sync"

	"github.com/keybase/client/go/externals"
	"github.com/keybase/client/go/libkb"
	"github.com/keybase/client/go/logger"
	"github.com/keybase/client/go/protocol/keybase1"
	"github.com/keybase/client/go/pvlsource"
	"github.com/keybase/client/go/service"
	"github.com/keybase/go-framed-msgpack-rpc/rpc"
	"github.com/keybase/kbfs/fsrpc"
	"github.com/keybase/kbfs/libkbfs"
)

var kbCtx *libkb.GlobalContext
var conn net.Conn
var startOnce sync.Once
var logSendContext libkb.LogSendContext
var kbfsConfig libkbfs.Config

// InitOnce runs the Keybase services (only runs one time)
func InitOnce(homeDir string, logFile string, runModeStr string, accessGroupOverride bool) {
	startOnce.Do(func() {
		if err := Init(homeDir, logFile, runModeStr, accessGroupOverride); err != nil {
			kbCtx.Log.Errorf("Init error: %s", err)
		}
	})
}

// Init runs the Keybase services
func Init(homeDir string, logFile string, runModeStr string, accessGroupOverride bool) error {
	fmt.Println("Go: Initializing")
	if logFile != "" {
		fmt.Printf("Go: Using log: %s\n", logFile)
	}

	kbCtx = libkb.G
	kbCtx.Init()
	kbCtx.SetServices(externals.GetServices())
	pvlsource.NewPvlSourceAndInstall(kbCtx)
	usage := libkb.Usage{
		Config:    true,
		API:       true,
		KbKeyring: true,
	}
	runMode, err := libkb.StringToRunMode(runModeStr)
	if err != nil {
		return err
	}
	config := libkb.AppConfig{
		HomeDir:                     homeDir,
		LogFile:                     logFile,
		RunMode:                     runMode,
		Debug:                       true,
		LocalRPCDebug:               "",
		SecurityAccessGroupOverride: accessGroupOverride,
	}
	err = kbCtx.Configure(config, usage)
	if err != nil {
		return err
	}

	svc := service.NewService(kbCtx, false)
	svc.StartLoopbackServer()
	kbCtx.SetService()
	uir := service.NewUIRouter(kbCtx)
	kbCtx.SetUIRouter(uir)
	svc.RunBackgroundOperations(uir)

	serviceLog := config.GetLogFile()
	logs := libkb.Logs{
		Service: serviceLog,
	}

	logSendContext = libkb.LogSendContext{
		Contextified: libkb.NewContextified(kbCtx),
		Logs:         logs,
	}

	// FIXME (MBG): This is causing RPC responses to sometimes not be recieved
	// on iOS. Repro by hooking up getExtendedStatus to a button in the iOS
	// client and watching JS logs. Disabling until we have a root cause / fix.
	kbfsParams := libkbfs.DefaultInitParams(kbCtx)
	// Avoid lots of background routines.
	kbfsParams.Mode = libkbfs.InitMinimalString
	kbfsConfig, err = libkbfs.Init(kbCtx, kbfsParams, serviceCn{}, func() {}, kbCtx.Log)
	if err != nil {
		return err
	}

	return Reset()
}

type serviceCn struct {
	ctx *libkb.GlobalContext
}

func (s serviceCn) NewKeybaseService(config libkbfs.Config, params libkbfs.InitParams, ctx libkbfs.Context, log logger.Logger) (libkbfs.KeybaseService, error) {
	keybaseService := libkbfs.NewKeybaseDaemonRPC(config, ctx, log, true, nil)
	keybaseService.AddProtocols([]rpc.Protocol{
		keybase1.FsProtocol(fsrpc.NewFS(config, log)),
	})
	return keybaseService, nil
}

func (s serviceCn) NewCrypto(config libkbfs.Config, params libkbfs.InitParams, ctx libkbfs.Context, log logger.Logger) (libkbfs.Crypto, error) {
	return libkbfs.NewCryptoClientRPC(config, ctx), nil
}

// LogSend sends a log to Keybase
func LogSend(feedback string, sendLogs bool, uiLogPath string) (string, error) {
	logSendContext.Logs.Desktop = uiLogPath
	return logSendContext.LogSend(fmt.Sprintf("{\"feedback\": \"%s\"}", feedback), sendLogs, 5*1024*1024)
}

// WriteB64 sends a base64 encoded msgpack rpc payload
func WriteB64(str string) error {
	data, err := base64.StdEncoding.DecodeString(str)
	if err != nil {
		return fmt.Errorf("Base64 decode error: %s; %s", err, str)
	}
	n, err := conn.Write(data)
	if err != nil {
		return fmt.Errorf("Write error: %s", err)
	}
	if n != len(data) {
		return errors.New("Did not write all the data")
	}
	return nil
}

const targetBufferSize = 50 * 1024

// bufferSize must be divisible by 3 to ensure that we don't split
// our b64 encode across a payload boundary if we go over our buffer
// size.
const bufferSize = targetBufferSize - (targetBufferSize % 3)

// buffer for the conn.Read
var buffer = make([]byte, bufferSize)

// ReadB64 is a blocking read for base64 encoded msgpack rpc data.
// It is called serially by the mobile run loops.
func ReadB64() (string, error) {
	n, err := conn.Read(buffer)
	if n > 0 && err == nil {
		str := base64.StdEncoding.EncodeToString(buffer[0:n])
		return str, nil
	}

	if err != nil {
		// Attempt to fix the connection
		Reset()
		return "", fmt.Errorf("Read error: %s", err)
	}

	return "", nil
}

// Reset resets the socket connection
func Reset() error {
	if conn != nil {
		conn.Close()
	}

	var err error
	conn, err = kbCtx.LoopbackListener.Dial()
	if err != nil {
		return fmt.Errorf("Socket error: %s", err)
	}
	return nil
}

// Version returns semantic version string
func Version() string {
	return libkb.VersionString()
}
<commit_msg>init kbfs in a goroutine so we dont get stuck (#6376)<commit_after>// Copyright 2015 Keybase, Inc. All rights reserved. Use of
// this source code is governed by the included BSD license.

package keybase

import (
	"encoding/base64"
	"errors"
	"fmt"
	"net"
	"sync"

	"github.com/keybase/client/go/externals"
	"github.com/keybase/client/go/libkb"
	"github.com/keybase/client/go/logger"
	"github.com/keybase/client/go/protocol/keybase1"
	"github.com/keybase/client/go/pvlsource"
	"github.com/keybase/client/go/service"
	"github.com/keybase/go-framed-msgpack-rpc/rpc"
	"github.com/keybase/kbfs/fsrpc"
	"github.com/keybase/kbfs/libkbfs"
)

var kbCtx *libkb.GlobalContext
var conn net.Conn
var startOnce sync.Once
var logSendContext libkb.LogSendContext
var kbfsConfig libkbfs.Config

// InitOnce runs the Keybase services (only runs one time)
func InitOnce(homeDir string, logFile string, runModeStr string, accessGroupOverride bool) {
	startOnce.Do(func() {
		if err := Init(homeDir, logFile, runModeStr, accessGroupOverride); err != nil {
			kbCtx.Log.Errorf("Init error: %s", err)
		}
	})
}

// Init runs the Keybase services
func Init(homeDir string, logFile string, runModeStr string, accessGroupOverride bool) error {
	fmt.Println("Go: Initializing")
	if logFile != "" {
		fmt.Printf("Go: Using log: %s\n", logFile)
	}

	kbCtx = libkb.G
	kbCtx.Init()
	kbCtx.SetServices(externals.GetServices())
	pvlsource.NewPvlSourceAndInstall(kbCtx)
	usage := libkb.Usage{
		Config:    true,
		API:       true,
		KbKeyring: true,
	}
	runMode, err := libkb.StringToRunMode(runModeStr)
	if err != nil {
		return err
	}
	config := libkb.AppConfig{
		HomeDir:                     homeDir,
		LogFile:                     logFile,
		RunMode:                     runMode,
		Debug:                       true,
		LocalRPCDebug:               "",
		SecurityAccessGroupOverride: accessGroupOverride,
	}
	err = kbCtx.Configure(config, usage)
	if err != nil {
		return err
	}

	svc := service.NewService(kbCtx, false)
	svc.StartLoopbackServer()
	kbCtx.SetService()
	uir := service.NewUIRouter(kbCtx)
	kbCtx.SetUIRouter(uir)
	svc.RunBackgroundOperations(uir)

	serviceLog := config.GetLogFile()
	logs := libkb.Logs{
		Service: serviceLog,
	}

	logSendContext = libkb.LogSendContext{
		Contextified: libkb.NewContextified(kbCtx),
		Logs:         logs,
	}

	// FIXME (MBG): This is causing RPC responses to sometimes not be recieved
	// on iOS. Repro by hooking up getExtendedStatus to a button in the iOS
	// client and watching JS logs. Disabling until we have a root cause / fix.
	kbfsParams := libkbfs.DefaultInitParams(kbCtx)
	// Avoid lots of background routines.
	go func() {
		kbfsParams.Mode = libkbfs.InitMinimalString
		kbfsConfig, _ = libkbfs.Init(kbCtx, kbfsParams, serviceCn{}, func() {}, kbCtx.Log)
	}()

	return Reset()
}

type serviceCn struct {
	ctx *libkb.GlobalContext
}

func (s serviceCn) NewKeybaseService(config libkbfs.Config, params libkbfs.InitParams, ctx libkbfs.Context, log logger.Logger) (libkbfs.KeybaseService, error) {
	keybaseService := libkbfs.NewKeybaseDaemonRPC(config, ctx, log, true, nil)
	keybaseService.AddProtocols([]rpc.Protocol{
		keybase1.FsProtocol(fsrpc.NewFS(config, log)),
	})
	return keybaseService, nil
}

func (s serviceCn) NewCrypto(config libkbfs.Config, params libkbfs.InitParams, ctx libkbfs.Context, log logger.Logger) (libkbfs.Crypto, error) {
	return libkbfs.NewCryptoClientRPC(config, ctx), nil
}

// LogSend sends a log to Keybase
func LogSend(feedback string, sendLogs bool, uiLogPath string) (string, error) {
	logSendContext.Logs.Desktop = uiLogPath
	return logSendContext.LogSend(fmt.Sprintf("{\"feedback\": \"%s\"}", feedback), sendLogs, 5*1024*1024)
}

// WriteB64 sends a base64 encoded msgpack rpc payload
func WriteB64(str string) error {
	data, err := base64.StdEncoding.DecodeString(str)
	if err != nil {
		return fmt.Errorf("Base64 decode error: %s; %s", err, str)
	}
	n, err := conn.Write(data)
	if err != nil {
		return fmt.Errorf("Write error: %s", err)
	}
	if n != len(data) {
		return errors.New("Did not write all the data")
	}
	return nil
}

const targetBufferSize = 50 * 1024

// bufferSize must be divisible by 3 to ensure that we don't split
// our b64 encode across a payload boundary if we go over our buffer
// size.
const bufferSize = targetBufferSize - (targetBufferSize % 3)

// buffer for the conn.Read
var buffer = make([]byte, bufferSize)

// ReadB64 is a blocking read for base64 encoded msgpack rpc data.
// It is called serially by the mobile run loops.
func ReadB64() (string, error) {
	n, err := conn.Read(buffer)
	if n > 0 && err == nil {
		str := base64.StdEncoding.EncodeToString(buffer[0:n])
		return str, nil
	}

	if err != nil {
		// Attempt to fix the connection
		Reset()
		return "", fmt.Errorf("Read error: %s", err)
	}

	return "", nil
}

// Reset resets the socket connection
func Reset() error {
	if conn != nil {
		conn.Close()
	}

	var err error
	conn, err = kbCtx.LoopbackListener.Dial()
	if err != nil {
		return fmt.Errorf("Socket error: %s", err)
	}
	return nil
}

// Version returns semantic version string
func Version() string {
	return libkb.VersionString()
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"runtime"
)

const (
	VERSION = "0.38"
)

var cmdVersion = &Command{
	Run:       runVersion,
	UsageLine: "version",
	Short:     "print Weed File System version",
	Long:      `Version prints the Weed File System version`,
}

func runVersion(cmd *Command, args []string) bool {
	if len(args) != 0 {
		cmd.Usage()
	}

	fmt.Printf("version %s %s %s\n", VERSION, runtime.GOOS, runtime.GOARCH)
	return true
}
<commit_msg>prepare to release 0.38<commit_after>package main

import (
	"fmt"
	"runtime"
)

const (
	VERSION = "0.39"
)

var cmdVersion = &Command{
	Run:       runVersion,
	UsageLine: "version",
	Short:     "print Weed File System version",
	Long:      `Version prints the Weed File System version`,
}

func runVersion(cmd *Command, args []string) bool {
	if len(args) != 0 {
		cmd.Usage()
	}

	fmt.Printf("version %s %s %s\n", VERSION, runtime.GOOS, runtime.GOARCH)
	return true
}
<|endoftext|>


<commit_before>package goanna

import (
	"encoding/json"
	"log"
	"net/http"
	"time"
)

const (
	HEADER_CACHE_CONTROL = "Cache-Control"
	HEADER_CACHE_NOCACHE = "no-cache"
)

// Response is a http response that can be built up
type Response interface {
	Send(http.ResponseWriter)
	SetCookie(http.Cookie)
	ClearCookie(string)
	Cookies() []http.Cookie
	Content() []byte
	StatusCode() int
	SetStatusCode(int)
	Headers() http.Header
}

type OkResponse struct {
	Header  http.Header
	cookies []http.Cookie
	content []byte
	Code    int
}

func NewResponse() *OkResponse {
	return &OkResponse{
		Header:  http.Header{},
		cookies: make([]http.Cookie, 0),
		content: make([]byte, 0),
		Code:    http.StatusOK,
	}
}

func NewStringResponse(content string) Response {
	response := NewResponse()
	response.content = []byte(content)
	return response
}

func (r *OkResponse) Cookies() []http.Cookie {
	return r.cookies
}

func (r *OkResponse) Headers() http.Header {
	return r.Header
}

func (r *OkResponse) Content() []byte {
	return r.content
}

func (r *OkResponse) SetCookie(cookie http.Cookie) {
	r.cookies = append(r.cookies, cookie)
}

func (r *OkResponse) ClearCookie(name string) {
	c := http.Cookie{}
	c.Name = name
	c.Value = "none"
	c.MaxAge = -1
	c.Expires = time.Unix(1, 0)
	r.SetCookie(c)
}

func (r *OkResponse) SetContent(content []byte) {
	r.content = content
}

func (r *OkResponse) SendHeaders(w http.ResponseWriter) {
	for _, cookie := range r.cookies {
		http.SetCookie(w, &cookie)
	}

	keys := make([]string, 0, len(r.Header))
	for k := range r.Header {
		keys = append(keys, k)
	}
	for _, k := range keys {
		for _, v := range r.Header[k] {
			w.Header().Add(k, v)
		}
	}
}

func (r *OkResponse) Send(w http.ResponseWriter) {
	r.SendHeaders(w)
	w.WriteHeader(r.Code)
	w.Write([]byte(r.content))
}

func (r *OkResponse) SetNoCache() {
	r.Header.Set(HEADER_CACHE_CONTROL, HEADER_CACHE_NOCACHE)
}

func (r *OkResponse) StatusCode() int {
	return r.Code
}

func (r *OkResponse) SetStatusCode(code int) {
	r.Code = code
}

type ErrorResponse struct {
	*OkResponse
	Message string
}

func NewErrorResponse(message string, code int) *ErrorResponse {
	response := ErrorResponse{
		OkResponse: NewResponse(),
		Message:    message,
	}
	response.SetStatusCode(code)

	return &response
}

func (r *ErrorResponse) Send(w http.ResponseWriter) {
	r.SendHeaders(w)
	http.Error(w, r.Message, r.Code)
	r.SetNoCache()
}

type RedirectResponse struct {
	*OkResponse
	urlStr string
}

func NewPermanentRedirectResponse(urlStr string) *RedirectResponse {
	response := RedirectResponse{
		OkResponse: NewResponse(),
		urlStr:     urlStr,
	}
	response.SetStatusCode(http.StatusMovedPermanently)

	return &response
}

func NewRedirectResponse(urlStr string) *RedirectResponse {
	response := RedirectResponse{
		OkResponse: NewResponse(),
		urlStr:     urlStr,
	}
	response.SetStatusCode(http.StatusFound)

	return &response
}

func (r *RedirectResponse) Send(w http.ResponseWriter) {
	w.Header().Set("Location", r.urlStr)
	r.SendHeaders(w)
	w.WriteHeader(r.Code)
}

func (r *RedirectResponse) Target() string {
	return r.urlStr
}

func NewJsonResponse(data interface{}) *OkResponse {
	json, err := json.Marshal(data)
	if err != nil {
		log.Panicln("Bad data for json marshalling")
	}

	response := NewResponse()
	response.content = []byte(json)
	response.Header.Set("Content-Type", "application/json")

	return response
}

func NewJsonpResponse(callback string, data interface{}) *OkResponse {
	json, err := json.Marshal(data)
	if err != nil {
		log.Panicln("Bad data for json marshalling")
	}
	body := append([]byte(callback+"("), json...)
	body = append(body, []byte(");")...)

	response := NewResponse()
	response.content = body
	response.Header.Set("Content-Type", "application/javascript")

	return response
}
<commit_msg>Refactor JsonResponse<commit_after>package goanna

import (
	"encoding/json"
	"log"
	"net/http"
	"time"
)

const (
	HEADER_CACHE_CONTROL = "Cache-Control"
	HEADER_CACHE_NOCACHE = "no-cache"
)

// Response is a http response that can be built up
type Response interface {
	Send(http.ResponseWriter)
	SetCookie(http.Cookie)
	ClearCookie(string)
	Cookies() []http.Cookie
	Content() []byte
	StatusCode() int
	SetStatusCode(int)
	Headers() http.Header
}

type OkResponse struct {
	Header  http.Header
	cookies []http.Cookie
	content []byte
	Code    int
}

func NewResponse() *OkResponse {
	return &OkResponse{
		Header:  http.Header{},
		cookies: make([]http.Cookie, 0),
		content: make([]byte, 0),
		Code:    http.StatusOK,
	}
}

func NewStringResponse(content string) Response {
	response := NewResponse()
	response.content = []byte(content)
	return response
}

func (r *OkResponse) Cookies() []http.Cookie {
	return r.cookies
}

func (r *OkResponse) Headers() http.Header {
	return r.Header
}

func (r *OkResponse) Content() []byte {
	return r.content
}

func (r *OkResponse) SetCookie(cookie http.Cookie) {
	r.cookies = append(r.cookies, cookie)
}

func (r *OkResponse) ClearCookie(name string) {
	c := http.Cookie{}
	c.Name = name
	c.Value = "none"
	c.MaxAge = -1
	c.Expires = time.Unix(1, 0)
	r.SetCookie(c)
}

func (r *OkResponse) SetContent(content []byte) {
	r.content = content
}

func (r *OkResponse) SendHeaders(w http.ResponseWriter) {
	for _, cookie := range r.cookies {
		http.SetCookie(w, &cookie)
	}

	keys := make([]string, 0, len(r.Header))
	for k := range r.Header {
		keys = append(keys, k)
	}
	for _, k := range keys {
		for _, v := range r.Header[k] {
			w.Header().Add(k, v)
		}
	}
}

func (r *OkResponse) Send(w http.ResponseWriter) {
	r.SendHeaders(w)
	w.WriteHeader(r.Code)
	w.Write([]byte(r.content))
}

func (r *OkResponse) SetNoCache() {
	r.Header.Set(HEADER_CACHE_CONTROL, HEADER_CACHE_NOCACHE)
}

func (r *OkResponse) StatusCode() int {
	return r.Code
}

func (r *OkResponse) SetStatusCode(code int) {
	r.Code = code
}

type ErrorResponse struct {
	*OkResponse
	Message string
}

func NewErrorResponse(message string, code int) *ErrorResponse {
	response := ErrorResponse{
		OkResponse: NewResponse(),
		Message:    message,
	}
	response.SetStatusCode(code)

	return &response
}

func (r *ErrorResponse) Send(w http.ResponseWriter) {
	r.SendHeaders(w)
	http.Error(w, r.Message, r.Code)
	r.SetNoCache()
}

type RedirectResponse struct {
	*OkResponse
	urlStr string
}

func NewPermanentRedirectResponse(urlStr string) *RedirectResponse {
	response := RedirectResponse{
		OkResponse: NewResponse(),
		urlStr:     urlStr,
	}
	response.SetStatusCode(http.StatusMovedPermanently)

	return &response
}

func NewRedirectResponse(urlStr string) *RedirectResponse {
	response := RedirectResponse{
		OkResponse: NewResponse(),
		urlStr:     urlStr,
	}
	response.SetStatusCode(http.StatusFound)

	return &response
}

func (r *RedirectResponse) Send(w http.ResponseWriter) {
	w.Header().Set("Location", r.urlStr)
	r.SendHeaders(w)
	w.WriteHeader(r.Code)
}

func (r *RedirectResponse) Target() string {
	return r.urlStr
}

type JsonResponse struct {
	*OkResponse
}

func NewJsonResponse() *JsonResponse {
	response := JsonResponse{NewResponse()}
	response.Header.Set("Content-Type", "application/json")

	return &response
}

func (this *JsonResponse) SetData(data interface{}) {
	json, err := json.Marshal(data)
	if err != nil {
		log.Panicln("Bad data for json marshalling")
	}

	this.SetContent(json)
}

func NewJsonDataResponse(data interface{}) *JsonResponse {
	response := NewJsonResponse()
	response.SetData(data)

	return response
}

func NewJsonpResponse(callback string, data interface{}) *OkResponse {
	json, err := json.Marshal(data)
	if err != nil {
		log.Panicln("Bad data for json marshalling")
	}
	body := append([]byte(callback+"("), json...)
	body = append(body, []byte(");")...)

	response := NewResponse()
	response.content = body
	response.Header.Set("Content-Type", "application/javascript")

	return response
}
<|endoftext|>


<commit_before>package google

import (
	"fmt"
	calendar "google.golang.org/api/calendar/v3"
	"net/http"
	"time"
)

const (
	TZ_TAIWAN = "Asia/Taipei"

	SCOPE_CALENDAR = calendar.CalendarScope
	YYYYMMDD       = "2006-01-02"
)

type Calendar struct {
	Id       string
	Timezone *time.Location
	svc      *calendar.Service
}
type Event struct {
	IsAllDay bool
	Start    time.Time
	End      time.Time
}

func NewCalendar(oauthClient *http.Client, id, tz string) (*Calendar, error) {
	svc, err := calendar.New(oauthClient)
	if err != nil {
		return nil, err
	}
	loc, err := time.LoadLocation(tz)
	if err != nil {
		return nil, err
	}
	return &Calendar{id, loc, svc}, nil
}

//NextFewDaysFristEvent return datetime array with the filtered event summary.
//It use the first match event, and ignore others same day event
//It always return same length array with requested `days`, even if error occurs
func (c *Calendar) NextFewDaysFristEvent(filterName string, days int) ([]Event, error) {
	var events = make([]Event, days)

	now := time.Now().In(c.Timezone)
	today := now.Format(time.RFC3339)
	lastDay := now.AddDate(0, 0, days).Format(time.RFC3339)

	res, err := c.svc.Events.List(c.Id).Q(filterName).Fields("items(start,end)").
		TimeMin(today).TimeMax(lastDay).SingleEvents(true).OrderBy("startTime").
		TimeZone(c.Timezone.String()).Do()
	if err != nil {
		return events, err
	}

	events = getDaysFirstEvent(res.Items, now, days)

	return events, nil
}
func getDaysFirstEvent(evts []*calendar.Event, current time.Time, withinDays int) []Event {
	events := make([]Event, withinDays)
	thDay := 0

	for _, ev := range evts {
		var evs, eve time.Time
		var isAllDay bool

		if isAllDay = ev.Start.Date != ""; isAllDay {
			evs, _ = time.Parse(YYYYMMDD, ev.Start.Date)
			eve, _ = time.Parse(YYYYMMDD, ev.End.Date)
		} else {
			evs, _ = time.Parse(time.RFC3339, ev.Start.DateTime)
			eve, _ = time.Parse(time.RFC3339, ev.End.DateTime)
		}

		var diff int
		diff = daysAgo(evs, current)
		if diff >= withinDays {
			break
		}

		if diff == thDay {
			events[thDay] = MakeEvent(isAllDay, evs, eve)
			thDay++
		} else if diff > thDay {
			events[diff] = MakeEvent(isAllDay, evs, eve)
			thDay = diff + 1
		} else {
			continue
		}
	}

	return events
}

// daysAgo return elapsed days between times provided. Less than 24 hours will return zero
// Both time should be in same timezone, to avoid confused or unexpected result
func daysAgo(src, dest time.Time) int {
	dt1 := time.Date(src.Year(), src.Month(), src.Day(), 0, 0, 0, 0, src.Location())
	dt2 := time.Date(dest.Year(), dest.Month(), dest.Day(), 0, 0, 0, 0, dest.Location())

	diff := dt1.Sub(dt2).Hours() / 24
	return int(diff)
}
func MakeEvent(allDay bool, start, end time.Time) Event {
	return Event{allDay, start, end}
}

func CreateCalendar(oauthClient *http.Client, name, tz string) (string, error) {
	svc, err := calendar.New(oauthClient)
	if err != nil {
		return "", fmt.Errorf("Unable to create Calendar service: %v", err)
	}

	cal := &calendar.Calendar{Summary: name, TimeZone: tz}
	calRes, err := svc.Calendars.Insert(cal).Do()
	if err != nil {
		return "", fmt.Errorf("Unable to insert calendar: %v", err)
	}

	return calRes.Id, nil
}
func (c *Calendar) PutACL(owner, googleGroup string, writer []string) error {
	acl := &calendar.AclRule{Role: "owner",
		Scope: &calendar.AclRuleScope{"group", googleGroup}}

	if owner != "" {
		acl.Role = "owner"
		acl.Scope.Type = "user"
		acl.Scope.Value = owner
		if _, err := c.svc.Acl.Insert(c.Id, acl).Do(); err != nil {
			return err
		}
	}
	if googleGroup != "" {
		acl.Role = "writer"
		acl.Scope.Type = "group"
		acl.Scope.Value = googleGroup
		if _, err := c.svc.Acl.Insert(c.Id, acl).Do(); err != nil {
			return err
		}
	}
	for _, wt := range writer {
		if wt == "" {
			continue
		}
		acl.Role = "writer"
		acl.Scope.Type = "user"
		acl.Scope.Value = wt
		if _, err := c.svc.Acl.Insert(c.Id, acl).Do(); err != nil {
			return err
		}
	}

	return nil
}

func (c *Calendar) UpdateInfo(summary, description, location string) (*calendar.Calendar, error) {
	cal := &calendar.Calendar{}
	if summary != "" {
		cal.Summary = summary
	}
	if description != "" {
		cal.Description = description
	}
	if location != "" {
		cal.Location = location
	}

	return c.svc.Calendars.Patch(c.Id, cal).Do()
}
<commit_msg>Wrap calendar ACL api<commit_after>package google

import (
	"fmt"
	calendar "google.golang.org/api/calendar/v3"
	"net/http"
	"time"
)

const (
	TZ_TAIWAN = "Asia/Taipei"

	SCOPE_CALENDAR = calendar.CalendarScope
	YYYYMMDD       = "2006-01-02"
)

type Calendar struct {
	Id       string
	Timezone *time.Location
	svc      *calendar.Service
}
type Event struct {
	IsAllDay bool
	Start    time.Time
	End      time.Time
}

func NewCalendar(oauthClient *http.Client, id, tz string) (*Calendar, error) {
	svc, err := calendar.New(oauthClient)
	if err != nil {
		return nil, err
	}
	loc, err := time.LoadLocation(tz)
	if err != nil {
		return nil, err
	}
	return &Calendar{id, loc, svc}, nil
}

//NextFewDaysFristEvent return datetime array with the filtered event summary.
//It use the first match event, and ignore others same day event
//It always return same length array with requested `days`, even if error occurs
func (c *Calendar) NextFewDaysFristEvent(filterName string, days int) ([]Event, error) {
	var events = make([]Event, days)

	now := time.Now().In(c.Timezone)
	today := now.Format(time.RFC3339)
	lastDay := now.AddDate(0, 0, days).Format(time.RFC3339)

	res, err := c.svc.Events.List(c.Id).Q(filterName).Fields("items(start,end)").
		TimeMin(today).TimeMax(lastDay).SingleEvents(true).OrderBy("startTime").
		TimeZone(c.Timezone.String()).Do()
	if err != nil {
		return events, err
	}

	events = getDaysFirstEvent(res.Items, now, days)

	return events, nil
}
func getDaysFirstEvent(evts []*calendar.Event, current time.Time, withinDays int) []Event {
	events := make([]Event, withinDays)
	thDay := 0

	for _, ev := range evts {
		var evs, eve time.Time
		var isAllDay bool

		if isAllDay = ev.Start.Date != ""; isAllDay {
			evs, _ = time.Parse(YYYYMMDD, ev.Start.Date)
			eve, _ = time.Parse(YYYYMMDD, ev.End.Date)
		} else {
			evs, _ = time.Parse(time.RFC3339, ev.Start.DateTime)
			eve, _ = time.Parse(time.RFC3339, ev.End.DateTime)
		}

		var diff int
		diff = daysAgo(evs, current)
		if diff >= withinDays {
			break
		}

		if diff == thDay {
			events[thDay] = MakeEvent(isAllDay, evs, eve)
			thDay++
		} else if diff > thDay {
			events[diff] = MakeEvent(isAllDay, evs, eve)
			thDay = diff + 1
		} else {
			continue
		}
	}

	return events
}

// daysAgo return elapsed days between times provided. Less than 24 hours will return zero
// Both time should be in same timezone, to avoid confused or unexpected result
func daysAgo(src, dest time.Time) int {
	dt1 := time.Date(src.Year(), src.Month(), src.Day(), 0, 0, 0, 0, src.Location())
	dt2 := time.Date(dest.Year(), dest.Month(), dest.Day(), 0, 0, 0, 0, dest.Location())

	diff := dt1.Sub(dt2).Hours() / 24
	return int(diff)
}
func MakeEvent(allDay bool, start, end time.Time) Event {
	return Event{allDay, start, end}
}

func CreateCalendar(oauthClient *http.Client, name, tz string) (string, error) {
	svc, err := calendar.New(oauthClient)
	if err != nil {
		return "", fmt.Errorf("Unable to create Calendar service: %v", err)
	}

	cal := &calendar.Calendar{Summary: name, TimeZone: tz}
	calRes, err := svc.Calendars.Insert(cal).Do()
	if err != nil {
		return "", fmt.Errorf("Unable to insert calendar: %v", err)
	}

	return calRes.Id, nil
}
func (c *Calendar) AddCalendarUserACL(role, scopeType, scopeValue string) error {
	acl := &calendar.AclRule{Role: role,
		Scope: &calendar.AclRuleScope{scopeType, scopeValue}}

	if _, err := c.svc.Acl.Insert(c.Id, acl).Do(); err != nil {
		return err
	}
	return nil
}
func (c *Calendar) DeleteCalendarUserACL(writer string) error {
	rule := fmt.Sprintf("user:%s", writer)
	return c.svc.Acl.Delete(c.Id, rule).Do()
}
func (c *Calendar) PutACL(owner, googleGroup string, writer []string) error {
	if owner != "" {
		if err := c.AddCalendarUserACL("owner", "user", owner); err != nil {
			return err
		}
	}
	if googleGroup != "" {
		if err := c.AddCalendarUserACL("writer", "group", googleGroup); err != nil {
			return err
		}
	}
	for _, wt := range writer {
		if wt == "" {
			continue
		}
		if err := c.AddCalendarUserACL("writer", "user", wt); err != nil {
			return err
		}
	}

	return nil
}

func (c *Calendar) UpdateInfo(summary, description, location string) (*calendar.Calendar, error) {
	cal := &calendar.Calendar{}
	if summary != "" {
		cal.Summary = summary
	}
	if description != "" {
		cal.Description = description
	}
	if location != "" {
		cal.Location = location
	}

	return c.svc.Calendars.Patch(c.Id, cal).Do()
}
<|endoftext|>


<commit_before>package grifts

import (
	"github.com/gobuffalo/buffalo"
	"github.com/kindlyops/havengrc/havenapi/actions"
)

func init() {
	buffalo.Grifts(actions.App())
}
<commit_msg>Refactor to remove old test code<commit_after><|endoftext|>


<commit_before>package main

import (
	"errors"
	"fmt"
	"log"
	"net"
	"os"
	"libproxy"
	"strings"
	"vsock"
)

func main() {
	host, port, container := parseHostContainerAddrs()

	err := exposePort(host, port)
	if err != nil {
		sendError(err)
	}
	p, err := libproxy.NewProxy(host, container)
	if err != nil {
		unexposePort(host)
		sendError(err)
	}
	go handleStopSignals(p)
	sendOK()
	p.Run()
	unexposePort(host)
	os.Exit(0)
}

func exposePort(host net.Addr, port int) error {
	name := host.String()
	log.Printf("exposePort %s\n", name)
	err := os.Mkdir("/port/"+name, 0)
	if err != nil {
		log.Printf("Failed to mkdir /port/%s: %#v\n", name, err)
		return err
	}
	ctl, err := os.OpenFile("/port/"+name+"/ctl", os.O_RDWR, 0)
	if err != nil {
		log.Printf("Failed to open /port/%s/ctl: %#v\n", name, err)
		return err
	}
	_, err = ctl.WriteString(fmt.Sprintf("%s:%d:%d", name, vsock.VSOCK_CID_SELF, vSockPortOffset + port))
	if err != nil {
		log.Printf("Failed to open /port/%s/ctl: %#v\n", name, err)
		return err
	}
	_, err = ctl.Seek(0, 0)
	if err != nil {
		log.Printf("Failed to seek on /port/%s/ctl: %#v\n", name, err)
		return err
	}
	results := make([]byte, 100)
	count, err := ctl.Read(results)
	if err != nil {
		log.Printf("Failed to read from /port/%s/ctl: %#v\n", name, err)
		return err
	}
	// We deliberately keep the control file open since 9P clunk
	// will trigger a shutdown on the host side.

	response := string(results[0:count])
	if strings.HasPrefix(response, "ERROR ") {
		os.Remove("/port/" + name + "/ctl")
		response = strings.Trim(response[6:], " \t\r\n")
		return errors.New(response)
	}

	return nil
}

func unexposePort(host net.Addr) {
	name := host.String()
	log.Printf("unexposePort %s\n", name)
	err := os.Remove("/port/" + name)
	if err != nil {
		log.Printf("Failed to remove /port/%s: %#v\n", name, err)
	}
}
<commit_msg>proxy: we don't need to explicitly unexposePort any more<commit_after>package main

import (
	"errors"
	"fmt"
	"log"
	"net"
	"os"
	"libproxy"
	"strings"
	"vsock"
)

func main() {
	host, port, container := parseHostContainerAddrs()

	err := exposePort(host, port)
	if err != nil {
		sendError(err)
	}
	p, err := libproxy.NewProxy(host, container)
	if err != nil {
		sendError(err)
	}
	go handleStopSignals(p)
	sendOK()
	p.Run()
	os.Exit(0)
}

func exposePort(host net.Addr, port int) error {
	name := host.String()
	log.Printf("exposePort %s\n", name)
	err := os.Mkdir("/port/"+name, 0)
	if err != nil {
		log.Printf("Failed to mkdir /port/%s: %#v\n", name, err)
		return err
	}
	ctl, err := os.OpenFile("/port/"+name+"/ctl", os.O_RDWR, 0)
	if err != nil {
		log.Printf("Failed to open /port/%s/ctl: %#v\n", name, err)
		return err
	}
	_, err = ctl.WriteString(fmt.Sprintf("%s:%d:%d", name, vsock.VSOCK_CID_SELF, vSockPortOffset + port))
	if err != nil {
		log.Printf("Failed to open /port/%s/ctl: %#v\n", name, err)
		return err
	}
	_, err = ctl.Seek(0, 0)
	if err != nil {
		log.Printf("Failed to seek on /port/%s/ctl: %#v\n", name, err)
		return err
	}
	results := make([]byte, 100)
	count, err := ctl.Read(results)
	if err != nil {
		log.Printf("Failed to read from /port/%s/ctl: %#v\n", name, err)
		return err
	}
	// We deliberately keep the control file open since 9P clunk
	// will trigger a shutdown on the host side.

	response := string(results[0:count])
	if strings.HasPrefix(response, "ERROR ") {
		os.Remove("/port/" + name + "/ctl")
		response = strings.Trim(response[6:], " \t\r\n")
		return errors.New(response)
	}

	return nil
}
<|endoftext|>


<commit_before>package server

import "testing"

func TestVHostWithDefaults(t *testing.T) {
	vh := NewVHost("/")

	if vh.name != "/" {
		t.Errorf("Invalid broker name: %s", vh.name)
	}

	if len(vh.exchanges) < 5 || vh.exchanges[""] == nil ||
		vh.exchanges["amq.direct"] == nil || vh.exchanges["amq.topic"] == nil {
		t.Errorf("VHost created without the required exchanges specified by amqp 0.9.1")
	}
}

func TestQueueDeclare(t *testing.T) {
	vh := NewVHost("/")

	q, err := vh.QueueDeclare("test-queue", nil)

	if err != nil {
		t.Error(err)
	}

	if q.Name() != "test-queue" {
		t.Errorf("Invalid queue name")
	}

	if len(vh.queues) != 1 || vh.queues["test-queue"] != q {
		t.Errorf("Failed to declare queue")
	}

	if q.Messages() != 0 || q.Consumers() != 0 {
		t.Errorf("Invalid number of messages or consumers")
	}
}

func TestBasicExchangeDeclare(t *testing.T) {
	vh := NewVHost("/")

	err := vh.ExchangeDeclare("neoway", "amq.direct", nil)

	if err == nil {
		t.Errorf("The exchange type correct name is direct")
		return
	}

	err = vh.ExchangeDeclare("neoway", "direct", nil)

	if err != nil {
		t.Error(err)
		return
	}

	if len(vh.exchanges) != 6 {
		t.Errorf("Exchange not properly created: %d", len(vh.exchanges))
		return
	}
}

func TestQueueBind(t *testing.T) {
	vh := NewVHost("/")

	err := vh.ExchangeDeclare("neoway", "direct", nil)

	if err != nil {
		t.Error(err)
		return
	}

	q, err := vh.QueueDeclare("queue-test", nil)

	if err != nil {
		t.Error(err)
		return
	}

	if q.Name() != "queue-test" {
		t.Errorf("Something wrong declaring queue")
		return
	}

	err = vh.QueueBind("queue-test", "process.data", "neoway", nil)

	if err != nil {
		t.Error(err)
		return
	}

	nwExchange, ok := vh.exchanges["neoway"].(*DirectExchange)

	if !ok {
		t.Errorf("Exchange neoway not created")
		return
	}

	if len(nwExchange.bindings) != 1 {
		t.Errorf("Binding not created")
		return
	}

	err = nwExchange.route("process.data", NewDelivery(&Channel{}, []byte{}, 1))

	if err != nil {
		t.Error(err)
		return
	}
}

func TestBasicPublish(t *testing.T) {
	vh := NewVHost("/")

	err := vh.ExchangeDeclare("neoway", "topic", nil)

	if err != nil {
		t.Error(err)
		return
	}

	q, err := vh.QueueDeclare("data", nil)

	if err != nil {
		t.Error(err)
		return
	}

	if q.Name() != "data" {
		t.Errorf("Invalid queue name")
		return
	}

	err = vh.QueueBind("data", "process.data", "neoway", nil)

	if err != nil {
		t.Error(err)
		return
	}

	err = vh.Publish("neoway", "process.data", NewDelivery(&Channel{}, []byte("teste"), 1), nil)

	if err != nil {
		t.Error(err)
		return
	}

	serverQueue, ok := q.(*Queue)

	if !ok {
		t.Errorf("Queue isn't of type *server.Queue")
		return
	}

	data := <-serverQueue.data

	if string(data.Body()) != "teste" {
		t.Errorf("Failed to publish message to specified route")
		return
	}
}
<commit_msg>Validating binding on queue was been done when to declare some queue<commit_after>package server

import "testing"

func TestVHostWithDefaults(t *testing.T) {
	vh := NewVHost("/")

	if vh.name != "/" {
		t.Errorf("Invalid broker name: %s", vh.name)
	}

	if len(vh.exchanges) < 5 || vh.exchanges[""] == nil ||
		vh.exchanges["amq.direct"] == nil || vh.exchanges["amq.topic"] == nil {
		t.Errorf("VHost created without the required exchanges specified by amqp 0.9.1")
	}
}

func TestQueueDeclare(t *testing.T) {
	vh := NewVHost("/")

	q, err := vh.QueueDeclare("test-queue", nil)

	if err != nil {
		t.Error(err)
	}

	if q.Name() != "test-queue" {
		t.Errorf("Invalid queue name")
	}

	if len(vh.queues) != 1 || vh.queues["test-queue"] != q {
		t.Errorf("Failed to declare queue")
	}

	if q.Messages() != 0 || q.Consumers() != 0 {
		t.Errorf("Invalid number of messages or consumers")
	}

	nwExchange, ok := vh.exchanges[""].(*DirectExchange)

	if !ok {
		t.Errorf("Exchange neoway not created")
		return
	}

	if len(nwExchange.bindings) != 1 {
		t.Errorf("Binding not created")
		return
	}
}

func TestBasicExchangeDeclare(t *testing.T) {
	vh := NewVHost("/")

	err := vh.ExchangeDeclare("neoway", "amq.direct", nil)

	if err == nil {
		t.Errorf("The exchange type correct name is direct")
		return
	}

	err = vh.ExchangeDeclare("neoway", "direct", nil)

	if err != nil {
		t.Error(err)
		return
	}

	if len(vh.exchanges) != 6 {
		t.Errorf("Exchange not properly created: %d", len(vh.exchanges))
		return
	}
}

func TestQueueBind(t *testing.T) {
	vh := NewVHost("/")

	err := vh.ExchangeDeclare("neoway", "direct", nil)

	if err != nil {
		t.Error(err)
		return
	}

	q, err := vh.QueueDeclare("queue-test", nil)

	if err != nil {
		t.Error(err)
		return
	}

	if q.Name() != "queue-test" {
		t.Errorf("Something wrong declaring queue")
		return
	}

	err = vh.QueueBind("queue-test", "process.data", "neoway", nil)

	if err != nil {
		t.Error(err)
		return
	}

	nwExchange, ok := vh.exchanges["neoway"].(*DirectExchange)

	if !ok {
		t.Errorf("Exchange neoway not created")
		return
	}

	if len(nwExchange.bindings) != 1 {
		t.Errorf("Binding not created")
		return
	}

	err = nwExchange.route("process.data", NewDelivery(&Channel{}, []byte{}, 1))

	if err != nil {
		t.Error(err)
		return
	}
}

func TestBasicPublish(t *testing.T) {
	vh := NewVHost("/")

	err := vh.ExchangeDeclare("neoway", "topic", nil)

	if err != nil {
		t.Error(err)
		return
	}

	q, err := vh.QueueDeclare("data", nil)

	if err != nil {
		t.Error(err)
		return
	}

	if q.Name() != "data" {
		t.Errorf("Invalid queue name")
		return
	}

	err = vh.QueueBind("data", "process.data", "neoway", nil)

	if err != nil {
		t.Error(err)
		return
	}

	err = vh.Publish("neoway", "process.data", NewDelivery(&Channel{}, []byte("teste"), 1), nil)

	if err != nil {
		t.Error(err)
		return
	}

	serverQueue, ok := q.(*Queue)

	if !ok {
		t.Errorf("Queue isn't of type *server.Queue")
		return
	}

	data := <-serverQueue.data

	if string(data.Body()) != "teste" {
		t.Errorf("Failed to publish message to specified route")
		return
	}
}
<|endoftext|>


<commit_before>package main

import (
	"fmt"
	"github.com/GoogleCloudPlatform/golang-docker/hello/vendor/internal"
	"github.com/gorilla/mux"
	"log"
	"net/http"
	"os"
)

func handle(w http.ResponseWriter, r *http.Request) {
	http.Redirect(w, r, fmt.Sprintf("/%s", internal.Secret), http.StatusFound)
}

func hello(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "Hello, %s! 세상아 안녕!", mux.Vars(r)["who"])
}

func main() {
	r := mux.NewRouter().StrictSlash(true)
	r.HandleFunc("/", handle).Methods("GET")
	r.HandleFunc("/{who}", hello).Methods("GET")

	http.Handle("/", r)
	envPort := os.Getenv("PORT")
	if len(envPort) == 0 {
		envPort = "8080"
	}
	listenOn := fmt.Sprintf(":%s", envPort)
	fmt.Println("listening on", listenOn)
	log.Fatal(http.ListenAndServe(listenOn, nil))
}
<commit_msg>move imports<commit_after>package main

import (
	"fmt"
	"log"
	"net/http"
	"os"

	"github.com/GoogleCloudPlatform/golang-docker/hello/vendor/internal"
	"github.com/gorilla/mux"
)

func handle(w http.ResponseWriter, r *http.Request) {
	http.Redirect(w, r, fmt.Sprintf("/%s", internal.Secret), http.StatusFound)
}

func hello(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "Hello, %s! 세상아 안녕!", mux.Vars(r)["who"])
}

func main() {
	r := mux.NewRouter().StrictSlash(true)
	r.HandleFunc("/", handle).Methods("GET")
	r.HandleFunc("/{who}", hello).Methods("GET")

	http.Handle("/", r)
	envPort := os.Getenv("PORT")
	if len(envPort) == 0 {
		envPort = "8080"
	}
	listenOn := fmt.Sprintf(":%s", envPort)
	fmt.Println("listening on", listenOn)
	log.Fatal(http.ListenAndServe(listenOn, nil))
}
<|endoftext|>